Map/FuncMover.cs
using System.Text.RegularExpressions;
/// <summary>
/// Moves and Rotates an Object.
/// </summary>
[Category( "Gameplay" ), Icon( "open_with" ), EditorHandle( Icon = "🚚" ), Tint(EditorTint.Green)]
public sealed class FuncMover : Component
{
[Property] bool StartOn { get; set; } = true;
//Linear Move
[Property, FeatureEnabled( "LinearMove", Icon = "🚀" )] public bool LinearMove { get; set; } = true;
[Property, Feature( "LinearMove" )] public Vector3 LinearDistance { get; set; } = Vector3.Up;
[Property, Feature( "LinearMove" )][Sync( SyncFlags.FromHost )] public float LinearSpeed { get; set; } = 10.0f;
[Property, Feature( "LinearMove" )] public bool LinearLoop { get; set; } = true;
[Property, Feature( "LinearMove" ), ShowIf(nameof(LinearLoop),true)] public float LinearPauseDuration { get; set; } = 0.0f;
//Rotate Move
[Property, FeatureEnabled( "RotateMove", Icon = "🔄" )] public bool RotateMove { get; set; } = false;
[Property, Feature( "RotateMove" )] public Angles RotationDirection { get; set; } = Angles.Zero;
[Property, Feature( "RotateMove" )][Sync( SyncFlags.FromHost )] public float RotationSpeed { get; set; } = 10.0f;
[Property, ReadOnly, Sync( SyncFlags.FromHost ), Group("Debug")]
bool IsOn { get; set; }
Transform startPos;
Vector3 targetPos;
private bool movingToTarget = true;
TimeSince pauseTimer = 0f;
bool isPaused = false;
protected override void OnStart()
{
base.OnStart();
IsOn = StartOn;
startPos = LocalTransform;
targetPos = startPos.Position + LinearDistance;
}
protected override void OnFixedUpdate()
{
if ( LinearMove )
{
if ( isPaused && pauseTimer > LinearPauseDuration )
{
isPaused = false;
}
Vector3 moveDirection = (startPos.Position - WorldPosition).Normal;
if ( LinearLoop )
{
moveDirection = movingToTarget ? (targetPos - WorldPosition).Normal : (startPos.Position - WorldPosition).Normal;
}
else
{
moveDirection = IsOn ? (targetPos - WorldPosition).Normal : (startPos.Position - WorldPosition).Normal;
}
if ( !isPaused && LinearLoop )
{
WorldPosition += moveDirection * LinearSpeed * Time.Delta;
}
else if (!LinearLoop )
{
WorldPosition += moveDirection * LinearSpeed * Time.Delta;
}
if ( movingToTarget && Vector3.DistanceBetween( WorldPosition, targetPos ) <= 1 )
{
movingToTarget = false;
WorldPosition = targetPos;
isPaused = true;
pauseTimer = 0f;
}
else if ( !movingToTarget && Vector3.DistanceBetween( WorldPosition, startPos.Position ) <= 1 )
{
movingToTarget = true;
WorldPosition = startPos.Position;
isPaused = true;
pauseTimer = 0f;
}
}
if ( RotateMove )
{
if(!IsOn ) return;
var delta = Time.Delta * RotationSpeed;
var rot = Rotation.From( RotationDirection ) * delta;
WorldRotation *= rot;
}
}
protected override void DrawGizmos()
{
base.DrawGizmos();
if ( LinearMove )
{
Gizmo.Draw.Color = Color.Green;
Gizmo.Draw.LineSphere( 0, 10f );
Gizmo.Draw.Color = Color.Red;
Gizmo.Draw.LineSphere( LinearDistance, 10f );
Gizmo.Draw.Color = Color.White;
Gizmo.Draw.Line( 0, LinearDistance );
Gizmo.Draw.Color = Color.Cyan;
Gizmo.Draw.SolidSphere( 0 + (LinearDistance * (MathF.Sin( Time.Now * (LinearSpeed / 100) ).Remap( -1, 1 ))), 10 );
}
}
public void Toggle() { ToggleInternal(); }
[Rpc.Host]
void ToggleInternal()
{
IsOn = !IsOn;
}
[Rpc.Host, Button( "TurnOn", "radio_button_checked" ), Group( "Debug" )]
public void TurnOn()
{
IsOn = true;
}
[Rpc.Host, Button("TurnOff", "radio_button_unchecked" ), Group( "Debug" )]
public void TurnOff()
{
IsOn = false;
}
[Rpc.Host]
public void SetLinearSpeed( float speed )
{
LinearSpeed = speed;
}
[Rpc.Host]
public void SetRotationSpeed( float speed )
{
RotationSpeed = speed;
}
}