更新
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace GraphicsCat
|
||||
{
|
||||
public class AutoRotate : MonoBehaviour, IMGUIDockable
|
||||
{
|
||||
public bool autoRotateEnabled = true;
|
||||
public Vector3 autoRotateSpeed = new Vector3(0, 5, 0);
|
||||
public bool guiEnabled = false;
|
||||
|
||||
Transform m_Transform;
|
||||
|
||||
void Start()
|
||||
{
|
||||
m_Transform = transform;
|
||||
if (guiEnabled)
|
||||
IMGUIDock.topRight.DockGUI(this);
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (autoRotateEnabled)
|
||||
{
|
||||
m_Transform.Rotate(autoRotateSpeed * Time.deltaTime, Space.Self);
|
||||
// m_Transform.localEulerAngles = m_Transform.localEulerAngles + autoRotateSpeed * Time.deltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDockGUI()
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button($"Auto Rotate {(autoRotateEnabled ? "O" : "X")}"))
|
||||
autoRotateEnabled = !autoRotateEnabled;
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 64d9c4976bbadb340bad62090109c21d
|
||||
timeCreated: 1535425205
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 328765
|
||||
packageName: LitPlus - URP Enhanced Lit Shader
|
||||
packageVersion: 1.0.1
|
||||
assetPath: Assets/GraphicsCat/DemoShared/Scripts/AutoRotate.cs
|
||||
uploadId: 820558
|
||||
531
Assets/OtherPlugins/GraphicsCat/DemoShared/Scripts/CameraRig.cs
Normal file
531
Assets/OtherPlugins/GraphicsCat/DemoShared/Scripts/CameraRig.cs
Normal file
@@ -0,0 +1,531 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GraphicsCat
|
||||
{
|
||||
public struct CameraMovementInput
|
||||
{
|
||||
public Vector3 translationDelta;
|
||||
public Vector3 rotationDelta;
|
||||
public float zoomDelta;
|
||||
public bool isDragging;
|
||||
}
|
||||
|
||||
public partial class CameraRig : MonoBehaviour, IMGUIDockable
|
||||
{
|
||||
public enum RigType
|
||||
{
|
||||
Free,
|
||||
TopDown,
|
||||
Locked,
|
||||
}
|
||||
|
||||
const int k_SpaceHeight = 10;
|
||||
|
||||
[Space(k_SpaceHeight)]
|
||||
public RigType rigType = RigType.Free;
|
||||
|
||||
[Space(k_SpaceHeight)]
|
||||
[Range(0, 20)]
|
||||
public float moveSpeed = 6f;
|
||||
[Range(0, 0.2f)]
|
||||
public float rotateSpeed = 0.1f;
|
||||
[Range(0, 200f)]
|
||||
public float zoomSpeed = 40f;
|
||||
|
||||
[Space(k_SpaceHeight)]
|
||||
public Transform targetTransform;
|
||||
|
||||
[Space(k_SpaceHeight)]
|
||||
public bool guiEnabled = true;
|
||||
|
||||
private Transform m_CachedTransform;
|
||||
|
||||
private Vector3 m_CameraInitialPosition;
|
||||
private Quaternion m_CameraInitialRotation;
|
||||
private Vector3 m_TargetInitialPosition;
|
||||
private Quaternion m_TargetInitialRotation;
|
||||
|
||||
private Touch m_MovementTouchInitial;
|
||||
private Touch m_MovementTouchCurrent;
|
||||
private Vector3 m_LastRotationMousePosition;
|
||||
private Vector3 m_LastDragMousePosition;
|
||||
private float m_MovementSpeedMultiplier;
|
||||
|
||||
private Vector3 m_TopDownPanDelta;
|
||||
|
||||
private bool m_IsInitialized;
|
||||
|
||||
private bool m_IsRigTypeSwitcherVisible = false;
|
||||
|
||||
private void ProcessCameraMovement(CameraMovementInput input)
|
||||
{
|
||||
bool isFreeType = (rigType == RigType.Free);
|
||||
bool isTopDownType = (rigType == RigType.TopDown);
|
||||
|
||||
if (input.translationDelta != Vector3.zero)
|
||||
{
|
||||
ApplyMovementDelta(input.translationDelta);
|
||||
}
|
||||
|
||||
if (input.rotationDelta != Vector3.zero && targetTransform != null)
|
||||
{
|
||||
if (isFreeType)
|
||||
{
|
||||
OrbitAroundTarget(input.rotationDelta);
|
||||
}
|
||||
}
|
||||
|
||||
if (input.zoomDelta != 0f)
|
||||
{
|
||||
if (isFreeType && targetTransform != null)
|
||||
{
|
||||
AdjustDistanceToTarget(input.zoomDelta);
|
||||
}
|
||||
else if (isTopDownType)
|
||||
{
|
||||
Vector3 zoomDeltaVector = m_CachedTransform.forward * input.zoomDelta;
|
||||
m_CachedTransform.position += zoomDeltaVector;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyMovementDelta(Vector3 delta)
|
||||
{
|
||||
m_CachedTransform.position += delta;
|
||||
|
||||
if (targetTransform != null)
|
||||
targetTransform.position += delta;
|
||||
}
|
||||
|
||||
private void OrbitAroundTarget(Vector3 delta)
|
||||
{
|
||||
if (targetTransform == null) return;
|
||||
|
||||
m_CachedTransform.RotateAround(targetTransform.position, Vector3.up, delta.x);
|
||||
m_CachedTransform.RotateAround(targetTransform.position, -m_CachedTransform.right, delta.y);
|
||||
}
|
||||
|
||||
private void RotateCamera(Vector3 delta)
|
||||
{
|
||||
if (targetTransform == null) return;
|
||||
|
||||
Vector3 referenceUp = Vector3.up;
|
||||
if (Vector3.Dot(m_CachedTransform.forward, Vector3.up) > 0.99f || Vector3.Dot(m_CachedTransform.forward, Vector3.up) < -0.99f)
|
||||
referenceUp = m_CachedTransform.right;
|
||||
|
||||
Vector3 cameraRight = Vector3.Cross(referenceUp, m_CachedTransform.forward).normalized;
|
||||
Vector3 cameraUp = Vector3.Cross(m_CachedTransform.forward, cameraRight).normalized;
|
||||
|
||||
Quaternion horizontalQuat = Quaternion.AngleAxis(delta.x, cameraUp);
|
||||
Quaternion verticalQuat = Quaternion.AngleAxis(delta.y, cameraRight);
|
||||
Quaternion totalRotation = horizontalQuat * verticalQuat;
|
||||
|
||||
Vector3 cameraToTarget = targetTransform.position - m_CachedTransform.position;
|
||||
Vector3 newCameraToTarget = totalRotation * cameraToTarget;
|
||||
|
||||
targetTransform.position = m_CachedTransform.position + newCameraToTarget;
|
||||
|
||||
m_CachedTransform.LookAt(targetTransform.position);
|
||||
}
|
||||
|
||||
private void AdjustDistanceToTarget(float delta)
|
||||
{
|
||||
if (targetTransform == null) return;
|
||||
|
||||
Vector3 cameraToTarget = m_CachedTransform.position - targetTransform.position;
|
||||
float newDistance = Mathf.Max(cameraToTarget.magnitude + delta, 0.1f);
|
||||
m_CachedTransform.position = targetTransform.position + cameraToTarget.normalized * newDistance;
|
||||
}
|
||||
|
||||
private void ResetToInitialState()
|
||||
{
|
||||
m_CachedTransform.SetPositionAndRotation(m_CameraInitialPosition, m_CameraInitialRotation);
|
||||
|
||||
if (targetTransform != null)
|
||||
targetTransform.SetPositionAndRotation(m_TargetInitialPosition, m_TargetInitialRotation);
|
||||
}
|
||||
|
||||
public void OnDockGUI()
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
{
|
||||
if (m_IsRigTypeSwitcherVisible)
|
||||
{
|
||||
var btnText = GetRigTypeDescription(rigType);
|
||||
if (GUILayout.Button(btnText))
|
||||
rigType = GetNextRigType(rigType);
|
||||
}
|
||||
|
||||
bool defaultStatus = true;
|
||||
defaultStatus &= (m_CachedTransform.position == m_CameraInitialPosition);
|
||||
defaultStatus &= (m_CachedTransform.rotation == m_CameraInitialRotation);
|
||||
|
||||
GUI.enabled = !defaultStatus;
|
||||
if (GUILayout.Button("Reset Camera"))
|
||||
ResetToInitialState();
|
||||
GUI.enabled = true;
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
m_CachedTransform = transform;
|
||||
|
||||
m_CameraInitialPosition = m_CachedTransform.position;
|
||||
m_CameraInitialRotation = m_CachedTransform.rotation;
|
||||
|
||||
if (targetTransform != null)
|
||||
{
|
||||
m_TargetInitialPosition = targetTransform.position;
|
||||
m_TargetInitialRotation = targetTransform.rotation;
|
||||
}
|
||||
|
||||
m_MovementTouchInitial.fingerId = int.MinValue;
|
||||
|
||||
m_IsInitialized = true;
|
||||
|
||||
UpdateDockGUI();
|
||||
}
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
UpdateDockGUI();
|
||||
}
|
||||
|
||||
private void UpdateDockGUI()
|
||||
{
|
||||
if (m_IsInitialized == false)
|
||||
return;
|
||||
|
||||
if (guiEnabled)
|
||||
IMGUIDock.topRight.DockGUI(this);
|
||||
else
|
||||
IMGUIDock.topRight.UndockGUI(this);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (rigType == RigType.Locked)
|
||||
return;
|
||||
|
||||
if (Application.isMobilePlatform)
|
||||
HandleMobileInput();
|
||||
else
|
||||
HandleDesktopInput();
|
||||
}
|
||||
|
||||
private Vector3 CalculateWorldPanDelta(Vector2 screenDelta)
|
||||
{
|
||||
var cam = GetComponent<Camera>();
|
||||
if (cam == null) return Vector3.zero;
|
||||
|
||||
float distance;
|
||||
|
||||
if (rigType == RigType.Free && targetTransform != null)
|
||||
{
|
||||
distance = Vector3.Distance(m_CachedTransform.position, targetTransform.position);
|
||||
}
|
||||
else if (rigType == RigType.TopDown)
|
||||
{
|
||||
float camHeight = m_CachedTransform.position.y;
|
||||
float forwardY = m_CachedTransform.forward.y;
|
||||
|
||||
if (Mathf.Abs(forwardY) < 1e-3 || Mathf.Abs(camHeight) < 1e-3)
|
||||
{
|
||||
distance = camHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
distance = camHeight / Mathf.Abs(forwardY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return Vector3.zero;
|
||||
}
|
||||
|
||||
float halfFOV = cam.fieldOfView * 0.5f;
|
||||
float worldHeightAtDistance = 2f * distance * Mathf.Tan(halfFOV * Mathf.Deg2Rad);
|
||||
float worldWidthAtDistance = worldHeightAtDistance * cam.aspect;
|
||||
|
||||
float percentX = screenDelta.x / Screen.width;
|
||||
float percentY = screenDelta.y / Screen.height;
|
||||
|
||||
Vector3 worldDelta = Vector3.zero;
|
||||
worldDelta -= m_CachedTransform.right * (percentX * worldWidthAtDistance);
|
||||
|
||||
if (rigType == RigType.Free)
|
||||
{
|
||||
worldDelta -= m_CachedTransform.up * (percentY * worldHeightAtDistance);
|
||||
}
|
||||
else if (rigType == RigType.TopDown)
|
||||
{
|
||||
worldDelta -= GetHorizontalForwardVector() * (percentY * worldHeightAtDistance);
|
||||
}
|
||||
|
||||
return worldDelta;
|
||||
}
|
||||
|
||||
private void HandleDesktopInput()
|
||||
{
|
||||
var input = new CameraMovementInput();
|
||||
var isTopDownType = rigType == RigType.TopDown;
|
||||
var isFreeType = (rigType == RigType.Free);
|
||||
var deltaTime = Time.smoothDeltaTime;
|
||||
|
||||
Vector3 keyboardMovement = Vector3.zero;
|
||||
|
||||
if (isFreeType && targetTransform != null)
|
||||
{
|
||||
if (Input.GetKey(KeyCode.W)) keyboardMovement += m_CachedTransform.forward;
|
||||
if (Input.GetKey(KeyCode.S)) keyboardMovement -= m_CachedTransform.forward;
|
||||
if (Input.GetKey(KeyCode.D)) keyboardMovement += m_CachedTransform.right;
|
||||
if (Input.GetKey(KeyCode.A)) keyboardMovement -= m_CachedTransform.right;
|
||||
if (Input.GetKey(KeyCode.E)) keyboardMovement += Vector3.up;
|
||||
if (Input.GetKey(KeyCode.Q)) keyboardMovement -= Vector3.up;
|
||||
}
|
||||
else if (isTopDownType)
|
||||
{
|
||||
if (Input.GetKey(KeyCode.Q)) input.zoomDelta += moveSpeed * deltaTime;
|
||||
if (Input.GetKey(KeyCode.E)) input.zoomDelta -= moveSpeed * deltaTime;
|
||||
|
||||
if (Input.GetKey(KeyCode.W)) keyboardMovement += GetHorizontalForwardVector();
|
||||
if (Input.GetKey(KeyCode.S)) keyboardMovement -= GetHorizontalForwardVector();
|
||||
if (Input.GetKey(KeyCode.D)) keyboardMovement += m_CachedTransform.right;
|
||||
if (Input.GetKey(KeyCode.A)) keyboardMovement -= m_CachedTransform.right;
|
||||
}
|
||||
|
||||
if (keyboardMovement != Vector3.zero)
|
||||
{
|
||||
m_MovementSpeedMultiplier += deltaTime;
|
||||
input.translationDelta = keyboardMovement.normalized * moveSpeed * deltaTime * m_MovementSpeedMultiplier;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_MovementSpeedMultiplier = 1;
|
||||
}
|
||||
|
||||
if (isFreeType && targetTransform != null)
|
||||
{
|
||||
if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1))
|
||||
m_LastRotationMousePosition = Input.mousePosition;
|
||||
if (Input.GetMouseButtonDown(2))
|
||||
m_LastDragMousePosition = Input.mousePosition;
|
||||
|
||||
if (Input.GetMouseButton(0))
|
||||
{
|
||||
var rotateMouseDelta = (Input.mousePosition - m_LastRotationMousePosition);
|
||||
if (rotateMouseDelta.sqrMagnitude > float.Epsilon)
|
||||
{
|
||||
input.rotationDelta = rotateMouseDelta * rotateSpeed;
|
||||
m_LastRotationMousePosition = Input.mousePosition;
|
||||
}
|
||||
}
|
||||
else if (Input.GetMouseButton(1))
|
||||
{
|
||||
var rotateMouseDelta = (Input.mousePosition - m_LastRotationMousePosition);
|
||||
if (rotateMouseDelta.sqrMagnitude > float.Epsilon)
|
||||
{
|
||||
var adjustedDelta = new Vector3(rotateMouseDelta.x * rotateSpeed, -rotateMouseDelta.y * rotateSpeed, 0);
|
||||
RotateCamera(adjustedDelta * 0.5f);
|
||||
m_LastRotationMousePosition = Input.mousePosition;
|
||||
}
|
||||
}
|
||||
else if (Input.GetMouseButton(2))
|
||||
{
|
||||
var mouseDelta = (Input.mousePosition - m_LastDragMousePosition);
|
||||
if (mouseDelta.sqrMagnitude > float.Epsilon)
|
||||
{
|
||||
input.translationDelta = CalculateWorldPanDelta(mouseDelta);
|
||||
input.isDragging = true;
|
||||
m_LastDragMousePosition = Input.mousePosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isTopDownType)
|
||||
{
|
||||
if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1) || Input.GetMouseButtonDown(2))
|
||||
m_LastDragMousePosition = Input.mousePosition;
|
||||
|
||||
if (Input.GetMouseButton(0) || Input.GetMouseButton(1) || Input.GetMouseButton(2))
|
||||
{
|
||||
var mouseDelta = (Input.mousePosition - m_LastDragMousePosition);
|
||||
if (mouseDelta.sqrMagnitude > float.Epsilon)
|
||||
{
|
||||
input.translationDelta = CalculateWorldPanDelta(mouseDelta);
|
||||
input.isDragging = true;
|
||||
|
||||
m_LastDragMousePosition = Input.mousePosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Input.mouseScrollDelta.y != 0 && IsMouseInViewPort())
|
||||
{
|
||||
if (isFreeType && targetTransform != null)
|
||||
{
|
||||
input.zoomDelta = -(Input.mouseScrollDelta.y * zoomSpeed * Time.deltaTime);
|
||||
}
|
||||
else if (isTopDownType)
|
||||
{
|
||||
input.zoomDelta = Input.mouseScrollDelta.y * zoomSpeed * Time.deltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessCameraMovement(input);
|
||||
}
|
||||
|
||||
private void HandleMobileInput()
|
||||
{
|
||||
if (rigType == RigType.Free)
|
||||
HandleFreeMobileInput();
|
||||
else if (rigType == RigType.TopDown)
|
||||
HandleTopDownMobileInput();
|
||||
}
|
||||
|
||||
private void HandleFreeMobileInput()
|
||||
{
|
||||
if (targetTransform == null) return;
|
||||
|
||||
var input = new CameraMovementInput();
|
||||
var touches = Input.touches;
|
||||
|
||||
if (touches.Length == 2)
|
||||
{
|
||||
Touch t0 = touches[0];
|
||||
Touch t1 = touches[1];
|
||||
|
||||
Vector2 t0PrevPos = t0.position - t0.deltaPosition;
|
||||
Vector2 t1PrevPos = t1.position - t1.deltaPosition;
|
||||
|
||||
float prevTouchDeltaMag = (t0PrevPos - t1PrevPos).magnitude;
|
||||
float currentTouchDeltaMag = (t0.position - t1.position).magnitude;
|
||||
|
||||
float pinchDelta = prevTouchDeltaMag - currentTouchDeltaMag;
|
||||
input.zoomDelta = pinchDelta * zoomSpeed * Time.smoothDeltaTime * 0.002f;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var touch in touches)
|
||||
{
|
||||
if (touch.phase == TouchPhase.Began)
|
||||
m_MovementTouchInitial = touch;
|
||||
else if (touch.phase == TouchPhase.Ended)
|
||||
{
|
||||
if (m_MovementTouchInitial.fingerId == touch.fingerId)
|
||||
m_MovementTouchInitial.fingerId = int.MinValue;
|
||||
}
|
||||
}
|
||||
|
||||
m_MovementTouchCurrent.fingerId = int.MinValue;
|
||||
foreach (var touch in touches)
|
||||
{
|
||||
if (touch.fingerId == m_MovementTouchInitial.fingerId)
|
||||
m_MovementTouchCurrent = touch;
|
||||
}
|
||||
|
||||
if (m_MovementTouchCurrent.fingerId != int.MinValue)
|
||||
{
|
||||
var rotateStrength = (m_MovementTouchCurrent.position - m_MovementTouchInitial.position) / Screen.width;
|
||||
if (rotateStrength != Vector2.zero)
|
||||
{
|
||||
var deltaTime = Time.smoothDeltaTime;
|
||||
var rotationDelta = 1000f * 20 * deltaTime * rotateSpeed * rotateStrength;
|
||||
input.rotationDelta = new Vector3(rotationDelta.x, rotationDelta.y, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProcessCameraMovement(input);
|
||||
}
|
||||
|
||||
private void HandleTopDownMobileInput()
|
||||
{
|
||||
var input = new CameraMovementInput();
|
||||
var touches = Input.touches;
|
||||
|
||||
foreach (var touch in touches)
|
||||
{
|
||||
if (touch.phase == TouchPhase.Began)
|
||||
m_MovementTouchInitial = touch;
|
||||
else if (touch.phase == TouchPhase.Ended)
|
||||
{
|
||||
if (m_MovementTouchInitial.fingerId == touch.fingerId)
|
||||
m_MovementTouchInitial.fingerId = int.MinValue;
|
||||
}
|
||||
}
|
||||
|
||||
m_MovementTouchCurrent.fingerId = int.MinValue;
|
||||
foreach (var touch in touches)
|
||||
{
|
||||
if (touch.fingerId == m_MovementTouchInitial.fingerId)
|
||||
m_MovementTouchCurrent = touch;
|
||||
}
|
||||
|
||||
if (m_MovementTouchCurrent.fingerId != int.MinValue)
|
||||
{
|
||||
if (m_MovementTouchCurrent.deltaPosition != Vector2.zero)
|
||||
{
|
||||
input.translationDelta = CalculateWorldPanDelta(m_MovementTouchCurrent.deltaPosition);
|
||||
input.isDragging = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_TopDownPanDelta *= Mathf.Lerp(1f, 0f, Time.smoothDeltaTime * 5);
|
||||
input.translationDelta = m_TopDownPanDelta;
|
||||
}
|
||||
|
||||
ProcessCameraMovement(input);
|
||||
}
|
||||
|
||||
private bool IsMouseInViewPort()
|
||||
{
|
||||
if (Input.mousePosition.x < 0 || Input.mousePosition.x > Screen.width ||
|
||||
Input.mousePosition.y < 0 || Input.mousePosition.y > Screen.height)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private Vector3 GetScreenSpaceUpVector()
|
||||
{
|
||||
var forward = m_CachedTransform.forward;
|
||||
if (Mathf.Abs(forward.y) < 0.01)
|
||||
return m_CachedTransform.up;
|
||||
else
|
||||
{
|
||||
forward.y = 0;
|
||||
return forward.normalized;
|
||||
}
|
||||
}
|
||||
|
||||
private Vector3 GetHorizontalForwardVector()
|
||||
{
|
||||
var forward = m_CachedTransform.forward;
|
||||
forward.y = 0;
|
||||
return forward.normalized;
|
||||
}
|
||||
|
||||
private string GetRigTypeDescription(RigType type)
|
||||
{
|
||||
var description = "Camera: Unknown Type";
|
||||
switch (type)
|
||||
{
|
||||
case RigType.Free: description = "Camera: Free"; break;
|
||||
case RigType.TopDown: description = "Camera: TopDown"; break;
|
||||
case RigType.Locked: description = "Camera: Locked"; break;
|
||||
}
|
||||
return description;
|
||||
}
|
||||
|
||||
private RigType GetNextRigType(RigType currentRigType)
|
||||
{
|
||||
var rigTypeCount = Enum.GetValues(typeof(RigType)).Length;
|
||||
return (RigType)(((int)currentRigType + 1) % rigTypeCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca55bded83820ca4598ef9e7ced323db
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 328765
|
||||
packageName: LitPlus - URP Enhanced Lit Shader
|
||||
packageVersion: 1.0.1
|
||||
assetPath: Assets/GraphicsCat/DemoShared/Scripts/CameraRig.cs
|
||||
uploadId: 820558
|
||||
@@ -0,0 +1,99 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace GraphicsCat
|
||||
{
|
||||
[ExecuteAlways]
|
||||
public class LookAtMainCamera : MonoBehaviour
|
||||
{
|
||||
public enum AlignMode { Full, YAxisOnly }
|
||||
|
||||
[Tooltip("Full: face camera on all axes. YAxisOnly: only rotate around world Y to face camera.")]
|
||||
public AlignMode alignMode = AlignMode.Full;
|
||||
|
||||
[Tooltip("Local self-rotation speed in degrees per second on each axis.")]
|
||||
public Vector3 selfRotationDegreesPerSecond = Vector3.zero;
|
||||
|
||||
[Tooltip("Optional euler offset (applied after aligning to camera).")]
|
||||
public Vector3 rotationOffsetEuler = Vector3.zero;
|
||||
|
||||
[Tooltip("Use LateUpdate for camera-following (recommended if camera moves in Update).")]
|
||||
public bool useLateUpdate = true;
|
||||
|
||||
[Tooltip("If true, the look direction will be inverted (useful if your mesh faces -Z by default).")]
|
||||
public bool invertLookDirection = true;
|
||||
|
||||
[Tooltip("If set, this camera will be used instead of Camera.main.")]
|
||||
public Camera overrideCamera;
|
||||
|
||||
// cached camera transform (will be updated if main camera changes)
|
||||
Transform targetCameraTransform;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
TryCacheCamera();
|
||||
}
|
||||
|
||||
void TryCacheCamera()
|
||||
{
|
||||
if (overrideCamera != null)
|
||||
{
|
||||
targetCameraTransform = overrideCamera.transform;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Camera.main != null)
|
||||
targetCameraTransform = Camera.main.transform;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (!useLateUpdate)
|
||||
AlignToCameraAndSelfRotate();
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
if (useLateUpdate)
|
||||
AlignToCameraAndSelfRotate();
|
||||
}
|
||||
|
||||
void AlignToCameraAndSelfRotate()
|
||||
{
|
||||
if (targetCameraTransform == null)
|
||||
TryCacheCamera();
|
||||
|
||||
// 1) Align to camera
|
||||
if (targetCameraTransform != null)
|
||||
{
|
||||
Vector3 camPos = targetCameraTransform.position;
|
||||
Vector3 toCam = camPos - transform.position;
|
||||
|
||||
// optionally invert direction if front faces -Z
|
||||
if (invertLookDirection)
|
||||
toCam = -toCam;
|
||||
|
||||
if (alignMode == AlignMode.Full)
|
||||
{
|
||||
if (toCam.sqrMagnitude > 0.0001f)
|
||||
transform.rotation = Quaternion.LookRotation(toCam.normalized, Vector3.up);
|
||||
}
|
||||
else // YAxisOnly
|
||||
{
|
||||
toCam.y = 0f;
|
||||
if (toCam.sqrMagnitude > 0.0001f)
|
||||
transform.rotation = Quaternion.LookRotation(toCam.normalized, Vector3.up);
|
||||
}
|
||||
|
||||
// apply an optional rotation offset after facing the camera
|
||||
if (rotationOffsetEuler != Vector3.zero)
|
||||
transform.rotation *= Quaternion.Euler(rotationOffsetEuler);
|
||||
}
|
||||
|
||||
// 2) Apply local self-rotation (spin) in local space
|
||||
if (selfRotationDegreesPerSecond != Vector3.zero)
|
||||
{
|
||||
transform.Rotate(selfRotationDegreesPerSecond * Time.deltaTime, Space.Self);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 822323b47cbe74b42910054c3bfb9579
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 328765
|
||||
packageName: LitPlus - URP Enhanced Lit Shader
|
||||
packageVersion: 1.0.1
|
||||
assetPath: Assets/GraphicsCat/DemoShared/Scripts/LookAtMainCamera.cs
|
||||
uploadId: 820558
|
||||
@@ -0,0 +1,96 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace GraphicsCat
|
||||
{
|
||||
[ExecuteAlways]
|
||||
public class ShadowDistance : MonoBehaviour
|
||||
{
|
||||
public enum Mode
|
||||
{
|
||||
Static,
|
||||
Dynamic
|
||||
}
|
||||
|
||||
public Mode mode = Mode.Static;
|
||||
|
||||
[EnableIf(nameof(mode), CompareFunction.Equal, Mode.Static)]
|
||||
[Range(1f, 100f)]
|
||||
public float staticDistance = 10f;
|
||||
|
||||
[InspectorDisplayName("Dynamic Distance Target")]
|
||||
[EnableIf(nameof(mode), CompareFunction.Equal, Mode.Dynamic)]
|
||||
public GameObject dynamicDistanceTarget;
|
||||
|
||||
[InspectorDisplayName("Dynamic Distance Offset")]
|
||||
[EnableIf(nameof(mode), CompareFunction.Equal, Mode.Dynamic)]
|
||||
public float dynamicDistanceOffset = 0f;
|
||||
|
||||
float m_TargetHalfSize = 0;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
UpdateShadowDistance();
|
||||
UpdateDynamicDistanceTargetHalfSize();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
UpdateShadowDistance();
|
||||
}
|
||||
|
||||
void OnValidate()
|
||||
{
|
||||
UpdateShadowDistance();
|
||||
UpdateDynamicDistanceTargetHalfSize();
|
||||
}
|
||||
|
||||
void UpdateShadowDistance()
|
||||
{
|
||||
if (mode == Mode.Static)
|
||||
SetShadowDistance(staticDistance);
|
||||
else
|
||||
UpdateShadowDistanceByLookTarget();
|
||||
}
|
||||
|
||||
void UpdateShadowDistanceByLookTarget()
|
||||
{
|
||||
var target = dynamicDistanceTarget;
|
||||
if (target == null)
|
||||
target = gameObject;
|
||||
|
||||
Camera mainCamera = Camera.main;
|
||||
if (mainCamera == null)
|
||||
return;
|
||||
|
||||
var targetDistance = (target.transform.position - mainCamera.transform.position).magnitude;
|
||||
var shadowDistance = targetDistance + m_TargetHalfSize + dynamicDistanceOffset;
|
||||
SetShadowDistance(shadowDistance);
|
||||
}
|
||||
|
||||
float GetShadowDistance()
|
||||
{
|
||||
var uprAsset = GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
|
||||
if (uprAsset != null)
|
||||
return uprAsset.shadowDistance;
|
||||
else
|
||||
return QualitySettings.shadowDistance;
|
||||
}
|
||||
|
||||
void SetShadowDistance(float val)
|
||||
{
|
||||
var urpAsset = GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
|
||||
if (urpAsset != null)
|
||||
urpAsset.shadowDistance = val;
|
||||
else
|
||||
QualitySettings.shadowDistance = val;
|
||||
}
|
||||
|
||||
void UpdateDynamicDistanceTargetHalfSize()
|
||||
{
|
||||
var bounds = BoundsUtils.GetHierarchyBounds(dynamicDistanceTarget);
|
||||
m_TargetHalfSize = bounds.extents.magnitude;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e3c94ff415e5b6419fe6590448f1106
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 328765
|
||||
packageName: LitPlus - URP Enhanced Lit Shader
|
||||
packageVersion: 1.0.1
|
||||
assetPath: Assets/GraphicsCat/DemoShared/Scripts/ShadowDistance.cs
|
||||
uploadId: 820558
|
||||
@@ -0,0 +1,305 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace GraphicsCat
|
||||
{
|
||||
public class SlideRotationController : MonoBehaviour, IMGUIDockable
|
||||
{
|
||||
private const float INERTIA_THRESHOLD = 0.1f; // Threshold to stop inertia rotation
|
||||
|
||||
[Header("Slide Rotation")]
|
||||
[InspectorDisplayName("Enable")]
|
||||
public bool slideRotationEnabled = false;
|
||||
[InspectorDisplayName("Sensitivity")]
|
||||
public Vector3 slideRotationSensitivity = new(0, 20, 0);
|
||||
[InspectorDisplayName("Inertia Damping")]
|
||||
[Range(0f, 1f)]
|
||||
public float inertiaDamping = 0.8f; // 0 = no inertia, 1 = maximum inertia
|
||||
|
||||
[Header("Auto Rotation")]
|
||||
[InspectorDisplayName("Enable")]
|
||||
public bool autoRotationEnabled = true;
|
||||
[InspectorDisplayName("Speed")]
|
||||
public Vector3 autoRotationSpeed = new(0, 5, 0);
|
||||
|
||||
[Header("Other")]
|
||||
public bool displayInGameGUI = false;
|
||||
|
||||
// Input state
|
||||
private bool m_IsDragging = false;
|
||||
private Vector3 m_LastPointerPosition = Vector3.zero;
|
||||
private Vector3 m_PointerDelta = Vector3.zero;
|
||||
private Transform m_Target = null;
|
||||
|
||||
// Touch input
|
||||
private Touch m_MainTouch;
|
||||
private bool m_IsTouchActive = false;
|
||||
|
||||
// Auto rotation
|
||||
private bool m_WasAutoRotationEnabled;
|
||||
private bool m_IsAutoRotationPaused = false;
|
||||
|
||||
// Inertia
|
||||
private Vector3 m_CurrentInertia = Vector3.zero;
|
||||
private Vector3 m_LastAngularVelocity = Vector3.zero;
|
||||
private bool m_HasAngularMovement = false; // Track if there was actual angular movement
|
||||
|
||||
private void Start()
|
||||
{
|
||||
m_Target = transform;
|
||||
IMGUIDock.topRight.DockGUI(this);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!slideRotationEnabled)
|
||||
return;
|
||||
|
||||
m_PointerDelta = Vector3.zero;
|
||||
|
||||
HandleMouseInput();
|
||||
|
||||
if (Application.isMobilePlatform)
|
||||
HandleTouchInput();
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
Vector3 slideRotationDelta = Vector3.zero;
|
||||
|
||||
if (slideRotationEnabled)
|
||||
{
|
||||
|
||||
// Handle manual rotation
|
||||
if (m_PointerDelta != Vector3.zero)
|
||||
{
|
||||
slideRotationDelta = ComputeRotationDelta(m_PointerDelta.x, m_PointerDelta.y);
|
||||
}
|
||||
// Apply inertia when not actively rotating
|
||||
else if (m_CurrentInertia.magnitude > INERTIA_THRESHOLD)
|
||||
{
|
||||
slideRotationDelta = m_CurrentInertia;
|
||||
m_CurrentInertia *= inertiaDamping;
|
||||
|
||||
if (m_CurrentInertia.magnitude < INERTIA_THRESHOLD)
|
||||
m_CurrentInertia = Vector3.zero;
|
||||
}
|
||||
|
||||
// Apply manual rotation or inertia
|
||||
if (slideRotationDelta != Vector3.zero)
|
||||
{
|
||||
Quaternion deltaRotation = Quaternion.Euler(slideRotationDelta * Time.fixedDeltaTime);
|
||||
m_Target.localRotation = deltaRotation * m_Target.localRotation;
|
||||
m_LastAngularVelocity = slideRotationDelta;
|
||||
m_HasAngularMovement = true; // There was actual rotation this frame
|
||||
}
|
||||
else
|
||||
{
|
||||
// No rotation this frame
|
||||
m_HasAngularMovement = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply auto rotation
|
||||
if (slideRotationDelta == Vector3.zero && autoRotationEnabled && !m_IsAutoRotationPaused)
|
||||
{
|
||||
ApplyAutoRotation();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply auto rotation according to configured speed.
|
||||
/// </summary>
|
||||
private void ApplyAutoRotation()
|
||||
{
|
||||
Quaternion rotation = Quaternion.Euler(autoRotationSpeed * Time.fixedDeltaTime);
|
||||
m_Target.localRotation = rotation * m_Target.localRotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute rotation delta based on pointer movement.
|
||||
/// </summary>
|
||||
private Vector3 ComputeRotationDelta(float x, float y)
|
||||
{
|
||||
return Vector3.Scale(new Vector3(y, x, 0), -slideRotationSensitivity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle mouse input for slide rotation.
|
||||
/// </summary>
|
||||
private void HandleMouseInput()
|
||||
{
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
if (IsPointerOverTarget(Input.mousePosition))
|
||||
{
|
||||
m_IsDragging = true;
|
||||
m_LastPointerPosition = Input.mousePosition;
|
||||
m_CurrentInertia = Vector3.zero; // Reset inertia when starting drag
|
||||
m_HasAngularMovement = false;
|
||||
|
||||
PauseAutoRotation();
|
||||
}
|
||||
}
|
||||
else if (Input.GetMouseButtonUp(0))
|
||||
{
|
||||
if (m_IsDragging)
|
||||
{
|
||||
m_IsDragging = false;
|
||||
// Only apply inertia if there was actual angular movement
|
||||
if (m_HasAngularMovement)
|
||||
ApplyInertia();
|
||||
else
|
||||
m_CurrentInertia = Vector3.zero; // No movement, no inertia
|
||||
|
||||
ResumeAutoRotation();
|
||||
}
|
||||
}
|
||||
else if (Input.GetMouseButton(0) && m_IsDragging)
|
||||
{
|
||||
Vector3 currentPosition = Input.mousePosition;
|
||||
m_PointerDelta = currentPosition - m_LastPointerPosition;
|
||||
m_LastPointerPosition = currentPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IsDragging = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle touch input for slide rotation.
|
||||
/// </summary>
|
||||
private void HandleTouchInput()
|
||||
{
|
||||
int touchCount = Input.touchCount;
|
||||
if (touchCount <= 0)
|
||||
{
|
||||
m_IsTouchActive = false;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < touchCount; i++)
|
||||
{
|
||||
Touch touch = Input.GetTouch(i);
|
||||
|
||||
switch (touch.phase)
|
||||
{
|
||||
case TouchPhase.Began:
|
||||
if (IsPointerOverTarget(touch.position))
|
||||
{
|
||||
m_MainTouch = touch;
|
||||
m_IsTouchActive = true;
|
||||
m_LastPointerPosition = touch.position;
|
||||
m_CurrentInertia = Vector3.zero; // Reset inertia when starting touch
|
||||
m_HasAngularMovement = false;
|
||||
PauseAutoRotation();
|
||||
}
|
||||
break;
|
||||
|
||||
case TouchPhase.Moved:
|
||||
if (m_IsTouchActive && touch.fingerId == m_MainTouch.fingerId)
|
||||
{
|
||||
Vector3 currentTouchPosition = touch.position;
|
||||
m_PointerDelta = currentTouchPosition - m_LastPointerPosition;
|
||||
m_LastPointerPosition = currentTouchPosition;
|
||||
}
|
||||
break;
|
||||
|
||||
case TouchPhase.Ended:
|
||||
case TouchPhase.Canceled:
|
||||
if (m_IsTouchActive && touch.fingerId == m_MainTouch.fingerId)
|
||||
{
|
||||
m_IsTouchActive = false;
|
||||
m_PointerDelta = Vector3.zero;
|
||||
// Only apply inertia if there was actual angular movement
|
||||
if (m_HasAngularMovement)
|
||||
ApplyInertia();
|
||||
else
|
||||
m_CurrentInertia = Vector3.zero; // No movement, no inertia
|
||||
|
||||
ResumeAutoRotation();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply inertia based on the last angular velocity.
|
||||
/// Inertia is directly proportional to the angular velocity at the moment of release.
|
||||
/// </summary>
|
||||
private void ApplyInertia()
|
||||
{
|
||||
// Only apply inertia if there was significant angular velocity
|
||||
// This ensures inertia magnitude correlates with rotation speed at release
|
||||
if (inertiaDamping > 0 && m_LastAngularVelocity.magnitude > INERTIA_THRESHOLD)
|
||||
m_CurrentInertia = m_LastAngularVelocity * inertiaDamping;
|
||||
else
|
||||
m_CurrentInertia = Vector3.zero;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Temporarily pause auto rotation during user interaction.
|
||||
/// </summary>
|
||||
private void PauseAutoRotation()
|
||||
{
|
||||
if (autoRotationEnabled)
|
||||
{
|
||||
m_WasAutoRotationEnabled = autoRotationEnabled;
|
||||
autoRotationEnabled = false;
|
||||
m_IsAutoRotationPaused = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resume auto rotation after user interaction ends.
|
||||
/// </summary>
|
||||
private void ResumeAutoRotation()
|
||||
{
|
||||
if (m_IsAutoRotationPaused)
|
||||
{
|
||||
autoRotationEnabled = m_WasAutoRotationEnabled;
|
||||
m_IsAutoRotationPaused = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the given screen point is over this object using renderer bounds.
|
||||
/// </summary>
|
||||
private bool IsPointerOverTarget(Vector3 screenPoint)
|
||||
{
|
||||
Camera camera = Camera.main;
|
||||
if (camera == null)
|
||||
return false;
|
||||
|
||||
Renderer[] renderers = m_Target.GetComponentsInChildren<Renderer>();
|
||||
if (renderers.Length == 0)
|
||||
return false;
|
||||
|
||||
Ray ray = camera.ScreenPointToRay(screenPoint);
|
||||
foreach (Renderer renderer in renderers)
|
||||
{
|
||||
if (renderer.enabled && renderer.bounds.IntersectRay(ray))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnDockGUI()
|
||||
{
|
||||
if (!displayInGameGUI)
|
||||
return;
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("Slide Rotation " + (slideRotationEnabled ? "O" : "X")))
|
||||
slideRotationEnabled = !slideRotationEnabled;
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("Auto Rotation " + (autoRotationEnabled ? "O" : "X")))
|
||||
autoRotationEnabled = !autoRotationEnabled;
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: db0cfd0a7c12f76469f9da3ae9ea890c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 328765
|
||||
packageName: LitPlus - URP Enhanced Lit Shader
|
||||
packageVersion: 1.0.1
|
||||
assetPath: Assets/GraphicsCat/DemoShared/Scripts/SlideRotationController.cs
|
||||
uploadId: 820558
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 305ecfd60dd56e344a675b8b415c585b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 328765
|
||||
packageName: LitPlus - URP Enhanced Lit Shader
|
||||
packageVersion: 1.0.1
|
||||
assetPath: Assets/GraphicsCat/DemoShared/Scripts/SoftBoundaryFloating.cs
|
||||
uploadId: 820558
|
||||
Reference in New Issue
Block a user