Files
Cielonos/Assets/OtherPlugins/GraphicsCat/DemoShared/Scripts/SoftBoundaryFloating.cs
SoulliesOfficial d15957c719 更新
2025-12-17 04:19:38 -05:00

107 lines
4.0 KiB
C#

using UnityEngine;
namespace GraphicsCat
{
public class SoftBoundaryFloating : MonoBehaviour
{
[Header("Floating Area")]
public Vector3 floatingAreaSize = new Vector3(5f, 5f, 5f);
[Tooltip("Start changing direction when close to boundary")]
public float boundaryBufferDistance = 0.5f;
[Header("Movement Settings")]
public float maxSpeed = 1f;
public float directionChangeSmoothness = 2f;
public Vector2 directionChangeInterval = new Vector2(2f, 5f);
private Vector3 _currentDirection;
private Vector3 _targetDirection;
private Vector3 _initialLocalPosition;
private float _nextDirectionChangeTime;
private void Start()
{
_initialLocalPosition = transform.localPosition;
_currentDirection = Random.insideUnitSphere.normalized;
_targetDirection = Random.insideUnitSphere.normalized;
ScheduleNextDirectionChange();
}
private void Update()
{
if (Time.time >= _nextDirectionChangeTime || IsNearBoundary())
{
_targetDirection = CalculateNewDirection();
ScheduleNextDirectionChange();
}
_currentDirection = Vector3.Slerp(
_currentDirection,
_targetDirection,
directionChangeSmoothness * Time.deltaTime
);
transform.localPosition += _currentDirection * maxSpeed * Time.deltaTime;
}
private bool IsNearBoundary()
{
Vector3 localPos = transform.localPosition - _initialLocalPosition;
float halfX = floatingAreaSize.x / 2f - boundaryBufferDistance;
float halfY = floatingAreaSize.y / 2f - boundaryBufferDistance;
float halfZ = floatingAreaSize.z / 2f - boundaryBufferDistance;
return Mathf.Abs(localPos.x) > halfX ||
Mathf.Abs(localPos.y) > halfY ||
Mathf.Abs(localPos.z) > halfZ;
}
private Vector3 CalculateNewDirection()
{
Vector3 localPos = transform.localPosition - _initialLocalPosition;
Vector3 awayFromEdge = Vector3.zero;
float weightX = Mathf.Clamp01((Mathf.Abs(localPos.x) - floatingAreaSize.x / 2f + boundaryBufferDistance) / boundaryBufferDistance);
float weightY = Mathf.Clamp01((Mathf.Abs(localPos.y) - floatingAreaSize.y / 2f + boundaryBufferDistance) / boundaryBufferDistance);
float weightZ = Mathf.Clamp01((Mathf.Abs(localPos.z) - floatingAreaSize.z / 2f + boundaryBufferDistance) / boundaryBufferDistance);
awayFromEdge.x = -Mathf.Sign(localPos.x) * weightX;
awayFromEdge.y = -Mathf.Sign(localPos.y) * weightY;
awayFromEdge.z = -Mathf.Sign(localPos.z) * weightZ;
Vector3 randomDir = Random.insideUnitSphere.normalized;
return (randomDir + awayFromEdge * 2f).normalized;
}
private void ScheduleNextDirectionChange()
{
_nextDirectionChangeTime = Time.time + Random.Range(
directionChangeInterval.x,
directionChangeInterval.y
);
}
// Correction: Gizmos position displays correctly in edit mode
private void OnDrawGizmosSelected()
{
Gizmos.color = Color.cyan;
// Key change: get the world matrix of the current object
Matrix4x4 gizmoMatrix = Matrix4x4.TRS(
transform.position,
transform.rotation,
transform.lossyScale
);
Gizmos.matrix = gizmoMatrix;
Gizmos.DrawWireCube(Vector3.zero, floatingAreaSize);
if (boundaryBufferDistance > 0)
{
Gizmos.color = Color.yellow;
Vector3 bufferSize = floatingAreaSize - Vector3.one * boundaryBufferDistance * 2f;
Gizmos.DrawWireCube(Vector3.zero, bufferSize);
}
}
}
}