136 lines
5.6 KiB
C#
136 lines
5.6 KiB
C#
using System;
|
|
using Unity.Collections;
|
|
using Unity.Entities;
|
|
using Unity.Mathematics;
|
|
using Unity.CharacterController;
|
|
|
|
public static class FirstPersonCharacterUtilities
|
|
{
|
|
public static quaternion GetCurrentWorldViewRotation(quaternion characterRotation, quaternion localCharacterViewRotation)
|
|
{
|
|
return math.mul(characterRotation, localCharacterViewRotation);
|
|
}
|
|
|
|
public static void GetCurrentWorldViewDirectionAndRotation(
|
|
quaternion characterRotation,
|
|
quaternion localCharacterViewRotation,
|
|
out float3 worldCharacterViewDirection,
|
|
out quaternion worldCharacterViewRotation)
|
|
{
|
|
worldCharacterViewRotation = GetCurrentWorldViewRotation(characterRotation, localCharacterViewRotation);
|
|
worldCharacterViewDirection = math.mul(worldCharacterViewRotation, math.forward());
|
|
}
|
|
|
|
public static void ComputeFinalRotationsFromTargetLookDirection(
|
|
ref quaternion characterRotation,
|
|
ref quaternion localCharacterViewRotation,
|
|
ref float3 targetLookDirection,
|
|
ref float viewPitchDegrees,
|
|
float viewRollDegrees,
|
|
float minViewPitchDegrees,
|
|
float maxViewPitchDegrees,
|
|
float3 characterUp)
|
|
{
|
|
// rotate character root to point at look direction on character up plane
|
|
float3 newCharacterForward = math.normalizesafe(MathUtilities.ProjectOnPlane(targetLookDirection, characterUp));
|
|
characterRotation = quaternion.LookRotationSafe(newCharacterForward, characterUp);
|
|
|
|
// calculate view pitch angles to look at target direction
|
|
viewPitchDegrees = math.degrees(MathUtilities.AngleRadians(newCharacterForward, targetLookDirection));
|
|
if (math.dot(characterUp, targetLookDirection) < 0f)
|
|
{
|
|
viewPitchDegrees *= -1f;
|
|
}
|
|
viewPitchDegrees = math.clamp(viewPitchDegrees, minViewPitchDegrees, maxViewPitchDegrees);
|
|
|
|
localCharacterViewRotation = CalculateLocalViewRotation(viewPitchDegrees, viewRollDegrees);
|
|
}
|
|
|
|
public static void ComputeFinalRotationsFromRotationDelta(
|
|
ref float viewPitchDegrees,
|
|
ref float characterRotationYDegrees,
|
|
float3 characterTransformUp,
|
|
float2 yawPitchDeltaDegrees,
|
|
float viewRollDegrees,
|
|
float minPitchDegrees,
|
|
float maxPitchDegrees,
|
|
out quaternion characterRotation,
|
|
out float canceledPitchDegrees,
|
|
out quaternion viewLocalRotation)
|
|
{
|
|
// Yaw
|
|
characterRotationYDegrees += yawPitchDeltaDegrees.x;
|
|
ComputeRotationFromYAngleAndUp(characterRotationYDegrees, characterTransformUp, out characterRotation);
|
|
|
|
// Pitch
|
|
viewPitchDegrees += yawPitchDeltaDegrees.y;
|
|
float viewPitchAngleDegreesBeforeClamp = viewPitchDegrees;
|
|
viewPitchDegrees = math.clamp(viewPitchDegrees, minPitchDegrees, maxPitchDegrees);
|
|
canceledPitchDegrees = yawPitchDeltaDegrees.y - (viewPitchAngleDegreesBeforeClamp - viewPitchDegrees);
|
|
|
|
viewLocalRotation = CalculateLocalViewRotation(viewPitchDegrees, viewRollDegrees);
|
|
}
|
|
|
|
public static void ComputeRotationFromYAngleAndUp(
|
|
float characterRotationYDegrees,
|
|
float3 characterTransformUp,
|
|
out quaternion characterRotation)
|
|
{
|
|
characterRotation = math.mul(MathUtilities.CreateRotationWithUpPriority(characterTransformUp, math.forward()), quaternion.Euler(0f, math.radians(characterRotationYDegrees), 0f));
|
|
}
|
|
|
|
public static void ComputeFinalRotationsFromRotationDelta(
|
|
ref quaternion characterRotation,
|
|
ref float viewPitchDegrees,
|
|
float2 yawPitchDeltaDegrees,
|
|
float viewRollDegrees,
|
|
float minPitchDegrees,
|
|
float maxPitchDegrees,
|
|
out float canceledPitchDegrees,
|
|
out quaternion viewLocalRotation)
|
|
{
|
|
// Yaw
|
|
quaternion yawRotation = quaternion.Euler(math.up() * math.radians(yawPitchDeltaDegrees.x));
|
|
characterRotation = math.mul(characterRotation, yawRotation);
|
|
|
|
// Pitch
|
|
viewPitchDegrees += yawPitchDeltaDegrees.y;
|
|
float viewPitchAngleDegreesBeforeClamp = viewPitchDegrees;
|
|
viewPitchDegrees = math.clamp(viewPitchDegrees, minPitchDegrees, maxPitchDegrees);
|
|
canceledPitchDegrees = yawPitchDeltaDegrees.y - (viewPitchAngleDegreesBeforeClamp - viewPitchDegrees);
|
|
|
|
viewLocalRotation = CalculateLocalViewRotation(viewPitchDegrees, viewRollDegrees);
|
|
}
|
|
|
|
public static quaternion CalculateLocalViewRotation(float viewPitchDegrees, float viewRollDegrees)
|
|
{
|
|
// Pitch
|
|
quaternion viewLocalRotation = quaternion.AxisAngle(-math.right(), math.radians(viewPitchDegrees));
|
|
|
|
// Roll
|
|
viewLocalRotation = math.mul(viewLocalRotation, quaternion.AxisAngle(math.forward(), math.radians(viewRollDegrees)));
|
|
|
|
return viewLocalRotation;
|
|
}
|
|
|
|
public static float3 ComputeTargetLookDirectionFromRotationAngles(
|
|
ref float viewPitchDegrees,
|
|
float minViewPitchDegrees,
|
|
float maxViewPitchDegrees,
|
|
float2 pitchYawDegrees,
|
|
quaternion characterRotation)
|
|
{
|
|
// Yaw
|
|
quaternion yawRotation = quaternion.Euler(math.up() * math.radians(pitchYawDegrees.x));
|
|
quaternion targetRotation = math.mul(characterRotation, yawRotation);
|
|
|
|
// Pitch
|
|
float tmpViewPitchAngleDegrees = viewPitchDegrees + pitchYawDegrees.y;
|
|
tmpViewPitchAngleDegrees = math.clamp(tmpViewPitchAngleDegrees, minViewPitchDegrees, maxViewPitchDegrees);
|
|
quaternion pitchRotation = quaternion.Euler(-math.right() * math.radians(tmpViewPitchAngleDegrees));
|
|
targetRotation = math.mul(targetRotation, pitchRotation);
|
|
|
|
return math.mul(targetRotation, math.forward());
|
|
}
|
|
}
|