83 lines
3.0 KiB
C#
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);
|
|
}
|
|
}
|
|
} |