| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 |
- using UnityEngine;
- public enum LogicTransformHitType
- {
- Cylinder = 0,
- Box = 1,
- Sphere = 2,
- }
- public struct InterpolateRecord
- {
- public float time;
- public Vector3 pos;
- }
- public struct InterpolateCache
- {
- const int cache_size = 5;
- InterpolateRecord[] records;
- int last;
- public void Init (Vector3 pos)
- {
- records = new InterpolateRecord[cache_size];
- for (int i = 0; i < cache_size; i++) {
- records [i].pos = pos;
- records [i].time = 0;
- }
- last = 0;
- }
- public void Reset (Vector3 pos)
- {
- for (int i = 0; i < cache_size; i++) {
- records [i].pos = pos;
- records [i].time = 0;
- }
- last = 0;
- }
- public void Add (Vector3 pos)
- {
- last = (last + 1) % cache_size;
- records [last].time = Time.time;
- records [last].pos = pos;
- }
- public bool Interpolate (float time, out Vector3 pos)
- {
- if (records [last].time <= time + 1e-3f) {
- pos = records [last].pos;
- return true;
- }
- int idx = (last + cache_size - 1) % cache_size;
- while (idx != last) {
- if (records [idx].time <= time) {
- pos = Vector3.Lerp (records [idx].pos, records [last].pos, (time - records [idx].time) / (records [last].time - records [idx].time));
- return false;
- }
- idx = (idx + cache_size - 1) % cache_size;
- }
- pos = records [(last + 1) % cache_size].pos;
- return false;
- }
- }
- public class LogicTransform
- {
- const float interpolate_position_delay = 0.066f;
- bool mGoDirty;
- bool mMatrixDirty;
- bool mPositionDirty;
- Matrix4x4 mLocalToWorld;
- Matrix4x4 mWorldToLocal;
- InterpolateCache mPositionCache;
- LogicTransform mParent;
- Vector3 mLocalPosition;
- Vector3 mLocalForward;
- bool mIsSettingFromParent;
- public Vector3 Position { get; protected set; }
- public Vector3 Forward { get; private set; }
- public Vector3 Up { get; private set; }
- public Vector3 Right { get { return Vector3.Cross (Up, Forward); } }
- public Vector3 Back { get { return Quaternion.AngleAxis(180, Vector3.up) * Forward; } }
- public float Scale { get; private set; }
- public int Layer { get; set; }
- public string LayerName { get { return LayerMask.LayerToName (Layer); } set { Layer = LayerMask.NameToLayer (value); } }
- public Vector3 HitSize { get; set; }
- public LogicTransformHitType HitType { get; set; }
- public float HitHeight { get { return HitSize.y; } }
- public float HitRadius { get { return HitSize.x; } }
- public bool KeepHorizontalLook { get; set; }
- public LogicTransform Parent { get { return mParent; } }
- public Vector3 LocalPosition {
- get { return mParent == null ? Position : mLocalPosition; }
- set {
- if (mParent != null) {
- mLocalPosition = value;
- UpdateFromParent ();
- } else
- SetPosition (value);
- }
- }
- public Vector3 LocalForward {
- get { return mParent == null ? Forward : mLocalForward; }
- set {
- if (mParent != null) {
- mLocalForward = value;
- UpdateFromParent ();
- } else
- LookForward (value);
- }
- }
- public LogicTransform ()
- {
- Position = Vector3.zero;
- Forward = Vector3.forward;
- Up = Vector3.up;
- KeepHorizontalLook = true;
- Scale = 1;
- HitSize = new Vector3 (0.5f, 1.8f, 0f);
- HitType = LogicTransformHitType.Cylinder;
- mPositionCache.Init (Position);
- mGoDirty = true;
- mPositionDirty = true;
- UpdateMatrix ();
- }
- public LogicTransform (Vector3 position, Vector3 forward, LogicTransformHitType hitType = LogicTransformHitType.Box, Vector3 hitSize = default(Vector3))
- {
- Position = position;
- Forward = forward;
- Up = Vector3.up;
- KeepHorizontalLook = true;
- Scale = 1;
- HitSize = hitSize;
- HitType = hitType;
- mPositionCache.Init (Position);
- mGoDirty = true;
- mPositionDirty = true;
- UpdateMatrix ();
- }
- public virtual void UpdateTransform (Transform transform)
- {
- if (mPositionDirty) {
- Vector3 pos;
- mPositionDirty = !mPositionCache.Interpolate(Time.time - interpolate_position_delay, out pos);
- transform.position = pos;
- }
- if (mGoDirty) {
- transform.LookAt (transform.position + Forward, Up);
- transform.localScale = Vector3.one * Scale;
- mGoDirty = false;
- }
- }
- public void ForceSync (Transform transform)
- {
- transform.position = Position;
- transform.LookAt (transform.position + Forward, Up);
- transform.localScale = Vector3.one * Scale;
- mPositionCache.Reset (Position);
- mGoDirty = false;
- mPositionDirty = false;
- }
- public virtual void SetPosition (Vector3 position)
- {
- mPositionCache.Add (position);
- mPositionDirty = true;
- mMatrixDirty = true;
- if (mParent != null && !mIsSettingFromParent)
- UpdateLocal ();
- }
- public virtual void SetRotation(Quaternion rot)
- {
- mMatrixDirty = true;
- if (mParent != null && !mIsSettingFromParent)
- UpdateLocal();
- }
- public virtual void LookForward (Vector3 forward, Vector3 up = default(Vector3))
- {
- if (KeepHorizontalLook) {
- forward = forward.SetY (0).normalized;
- if (forward.FEqual (Forward, 1e-3f))
- return;
- Forward = forward.normalized;
- Up = Vector3.up;
- } else {
- if (forward.FEqual (Forward, 1e-3f))
- return;
- Forward = forward.normalized;
- if (up != default(Vector3))
- Up = up.normalized;
- FixUpDir ();
- }
- mGoDirty = true;
- mMatrixDirty = true;
- if (mParent != null && !mIsSettingFromParent)
- UpdateLocal ();
- }
- public virtual void SetScale (float s)
- {
- Scale = s;
- mGoDirty = true;
- mMatrixDirty = true;
- }
- public void LookAt (Vector3 lookAt, Vector3 up = default(Vector3))
- {
- if (lookAt.FEqual (Position, 1e-2f))
- return;
- LookForward ((lookAt - Position).normalized, up);
- }
- public Vector3 TransformPoint (Vector3 v)
- {
- if (mMatrixDirty)
- UpdateMatrix ();
- return mLocalToWorld.MultiplyPoint (v);
- }
- public Vector3 InverseTransformPoint (Vector3 v)
- {
- if (mMatrixDirty)
- UpdateMatrix ();
- return mWorldToLocal.MultiplyPoint (v);
- }
- public Vector3 TransformDirection (Vector3 d)
- {
- if (mMatrixDirty)
- UpdateMatrix ();
- return mLocalToWorld.MultiplyVector (d);
- }
- public Vector3 InverseTransformDirection (Vector3 d)
- {
- if (mMatrixDirty)
- UpdateMatrix ();
- return mWorldToLocal.MultiplyVector (d);
- }
- public bool CheckHitBox (Vector3 pos, Vector3 dir, Vector3 size)
- {
- Vector3 offset = Position - pos;
- if (Mathf.Abs (Vector3.Dot (offset, Up) + 0.5f * HitHeight) > 0.5f * (size.y + HitHeight))
- return false;
- if (Mathf.Abs (Vector3.Dot (offset, dir)) > (0.5f * size.z + HitRadius))
- return false;
- return Mathf.Abs (Vector3.Dot (offset, Vector3.Cross (Up, dir))) <= (0.5f * size.x + HitRadius);
- }
- public bool CheckHitBoxUnscrict(Vector3 linkPos, Vector3 pos, Vector3 dir, Vector3 size)
- {
- Vector3 offset = linkPos - pos;
- if (Mathf.RoundToInt(Mathf.Abs(Vector3.Dot(offset, Up) + 0.5f * HitHeight) * 1e5f) > Mathf.RoundToInt(0.5f * (size.y + HitHeight)) * 1e5f)
- return false;
- if (Mathf.RoundToInt(Mathf.Abs(Vector3.Dot(offset, dir)) * 1e5f) > Mathf.RoundToInt((0.5f * size.z + HitRadius) * 1e5f))
- return false;
- return Mathf.RoundToInt(Mathf.Abs(Vector3.Dot(offset, Vector3.Cross(Up, dir))) * 1e5f) <= Mathf.RoundToInt((0.5f * size.x + HitRadius) * 1e5f);
- }
- public bool CheckHitBoxUnscrict (Vector3 pos, Vector3 dir, Vector3 size)
- {
- Vector3 offset = Position - pos;
- if (Mathf.RoundToInt (Mathf.Abs (Vector3.Dot (offset, Up) + 0.5f * HitHeight) * 1e5f) > Mathf.RoundToInt (0.5f * (size.y + HitHeight)) * 1e5f)
- return false;
- if (Mathf.RoundToInt (Mathf.Abs (Vector3.Dot (offset, dir)) * 1e5f) > Mathf.RoundToInt((0.5f * size.z + HitRadius) * 1e5f))
- return false;
- return Mathf.RoundToInt (Mathf.Abs (Vector3.Dot (offset, Vector3.Cross (Up, dir))) * 1e5f) <= Mathf.RoundToInt((0.5f * size.x + HitRadius) * 1e5f);
- }
- public bool CheckHitCylinder (Vector3 pos, float radius, float height)
- {
- Vector3 offset = Position - pos;
- if (offset.SetY (0).sqrMagnitude > (radius + HitRadius) * (radius + HitRadius))
- return false;
- return Mathf.Abs (offset.y + 0.5f * HitHeight) <= 0.5f * (height + HitHeight);
- }
- public void SetParent (LogicTransform parent, bool keepWorldTransform = false)
- {
- mParent = parent;
- if (mParent != null) {
- if (keepWorldTransform) {
- UpdateLocal ();
- } else {
- LocalPosition = Vector3.zero;
- LocalForward = Vector3.forward;
- }
- }
- }
- void UpdateLocal ()
- {
- mLocalPosition = mParent.InverseTransformPoint (Position);
- mLocalForward = mParent.InverseTransformDirection (Forward);
- }
- public void UpdateFromParent ()
- {
- mIsSettingFromParent = true;
- SetPosition (mParent.TransformPoint (mLocalPosition));
- LookForward (mParent.TransformDirection (Forward));
- mIsSettingFromParent = false;
- }
- void UpdateMatrix ()
- {
- mLocalToWorld.SetColumn (0, Right * Scale);
- mLocalToWorld.SetColumn (1, Up * Scale);
- mLocalToWorld.SetColumn (2, Forward * Scale);
- mLocalToWorld.SetColumn (3, new Vector4(Position.x, Position.y, Position.z, 1));
- mWorldToLocal = mLocalToWorld.inverse;
- mMatrixDirty = false;
- }
- void FixUpDir ()
- {
- float dot = Mathf.Abs (Vector3.Dot (Forward, Up));
- if (dot > 1 - 1e-4f) {
- if (Forward.FEqual (Vector3.up))
- Up = Vector3.Cross (Forward, Vector3.right);
- else
- Up = Vector3.Cross (Forward, Vector3.Cross (Vector3.up, Forward));
- } else if (dot > Mathf.Epsilon)
- Up = Vector3.Cross (Forward, Vector3.Cross (Up, Forward));
- }
- }
|