Files
GoakeFlax/Source/Game/Camera/WeaponSway.cs

83 lines
3.0 KiB
C#

using System;
using FlaxEngine;
namespace Game
{
public class WeaponSway : Script
{
private Actor cameraHolder;
private Actor rootActor;
public float swaySpeed = 3000f;
private float timeRemainder;
public override void OnStart()
{
rootActor = Actor.Parent.GetChild("RootActor");
cameraHolder = rootActor.GetChild("CameraHolder");
Actor.LocalOrientation = GetRotation();
}
private Quaternion GetRotation()
{
Quaternion pitch = cameraHolder.LocalOrientation;
Quaternion yawRoll = rootActor.LocalOrientation;
return yawRoll * pitch;
}
public override void OnLateUpdate()
{
Quaternion rotation = GetRotation();
Vector3 targetAngles = rotation.EulerAngles;
Vector3 angles = Actor.LocalOrientation.EulerAngles;
// Ensure the swaying is smooth when framerate fluctuates slightly
float remaining = Time.DeltaTime + timeRemainder;
const float minTime = 1f / 120f;
do
{
float stepTime = Mathf.Min(Time.DeltaTime, minTime);
remaining -= stepTime;
float swaySpeedScaled = swaySpeed * stepTime;
float deltaX = Mathf.DeltaAngle(angles.X, targetAngles.X);
float deltaY = Mathf.DeltaAngle(angles.Y, targetAngles.Y);
float deltaZ = Mathf.DeltaAngle(angles.Z, targetAngles.Z);
const float maxAngle = 30f;
if (deltaX > maxAngle)
angles.X -= maxAngle - deltaX;
else if (deltaX < -maxAngle)
angles.X += maxAngle + deltaX;
if (deltaY > maxAngle)
angles.Y -= maxAngle - deltaY;
else if (deltaY < -maxAngle)
angles.Y += maxAngle + deltaY;
if (deltaZ > maxAngle)
angles.Z -= maxAngle - deltaZ;
else if (deltaZ < -maxAngle)
angles.Z += maxAngle + deltaZ;
float percX = Mathf.Abs(deltaX) / maxAngle;
float percY = Mathf.Abs(deltaY) / maxAngle;
float percZ = Mathf.Abs(deltaZ) / maxAngle;
float minSpeed = swaySpeedScaled * 0.00001f * 0f;
Func<float, float> fun = f => Mathf.Pow(f, 1.3f);
angles.X = Mathf.MoveTowardsAngle(angles.X, targetAngles.X,
Math.Max(swaySpeedScaled * fun(percX), minSpeed));
angles.Y = Mathf.MoveTowardsAngle(angles.Y, targetAngles.Y,
Math.Max(swaySpeedScaled * fun(percY), minSpeed));
angles.Z = Mathf.MoveTowardsAngle(angles.Z, targetAngles.Z,
Math.Max(swaySpeedScaled * fun(percZ), minSpeed));
} while (remaining > minTime);
timeRemainder -= remaining;
Actor.LocalOrientation = Quaternion.Euler(angles);
}
}
}