更新
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user