Created
September 19, 2015 14:01
-
-
Save JakubNei/298a59e51d73592fa0eb to your computer and use it in GitHub Desktop.
My fancy custom UnityEngine.Transform like setup. Sorry, i just love doing stupid things like this.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Implements basic equals methods and bool converions, similar to UnityEngine.Object | |
/// </summary> | |
public class BaseObject | |
{ | |
public override bool Equals(object obj) | |
{ | |
return AreObjectsEqual(this, obj as BaseObject); | |
} | |
public override int GetHashCode() | |
{ | |
return base.GetHashCode(); | |
} | |
public static implicit operator string (BaseObject me) | |
{ | |
return me.ToString(); | |
} | |
public static implicit operator bool (BaseObject exists) | |
{ | |
return !AreObjectsEqual(exists, null); | |
} | |
public static bool operator ==(BaseObject x, BaseObject y) | |
{ | |
return AreObjectsEqual(x, y); | |
} | |
public static bool operator !=(BaseObject x, BaseObject y) | |
{ | |
return !AreObjectsEqual(x, y); | |
} | |
private static bool AreObjectsEqual(BaseObject lhs, BaseObject rhs) | |
{ | |
bool lhsIsNull = (object)lhs == null; | |
bool rhsIsNull = (object)rhs == null; | |
if (rhsIsNull && lhsIsNull) | |
{ | |
return true; | |
} | |
if (rhsIsNull) | |
{ | |
return !IsNativeObjectAlive(lhs); | |
} | |
if (lhsIsNull) | |
{ | |
return !IsNativeObjectAlive(rhs); | |
} | |
return (object)lhs == (object)rhs; | |
} | |
private static bool IsNativeObjectAlive(BaseObject o) | |
{ | |
return o.isAlive; | |
} | |
[System.NonSerialized] | |
private bool isAlive = true; | |
internal void SetAlive(bool isAlive) | |
{ | |
this.isAlive = isAlive; | |
} | |
public virtual string ToDebug() | |
{ | |
return ToString(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
public class FakeComponent : BaseObject | |
{ | |
public string name { get; set; } | |
GameObject unityGameObject; | |
public GameObject gameObject | |
{ | |
get | |
{ | |
return unityGameObject; | |
} | |
internal set | |
{ | |
unityGameObject = value; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine.Internal; | |
using UnityEngine; | |
public class Transform : FakeComponent, IEnumerable, IEnumerable<Transform> | |
{ | |
private sealed class Enumerator : IEnumerator, IEnumerator<Transform> | |
{ | |
private Transform outer; | |
private int currentIndex = -1; | |
public object Current | |
{ | |
get | |
{ | |
return this.outer.GetChild(this.currentIndex); | |
} | |
} | |
Transform IEnumerator<Transform>.Current | |
{ | |
get | |
{ | |
return this.outer.GetChild(this.currentIndex); | |
} | |
} | |
internal Enumerator(Transform outer) | |
{ | |
this.outer = outer; | |
} | |
public bool MoveNext() | |
{ | |
int childCount = this.outer.childCount; | |
return ++this.currentIndex < childCount; | |
} | |
public void Reset() | |
{ | |
this.currentIndex = -1; | |
} | |
public void Dispose() | |
{ | |
throw new NotImplementedException(); | |
} | |
} | |
/// <summary> | |
/// <para>The position of the transform in world space.</para> | |
/// </summary> | |
public Vector3 position | |
{ | |
get | |
{ | |
return unityEngineTransform.position; | |
} | |
set | |
{ | |
unityEngineTransform.position = value; | |
} | |
} | |
/// <summary> | |
/// <para>Position of the transform relative to the parent transform.</para> | |
/// </summary> | |
public Vector3 localPosition | |
{ | |
get | |
{ | |
return unityEngineTransform.localPosition; | |
} | |
set | |
{ | |
unityEngineTransform.localPosition = value; | |
} | |
} | |
/// <summary> | |
/// <para>The rotation as Euler angles in degrees.</para> | |
/// </summary> | |
public Vector3 eulerAngles | |
{ | |
get | |
{ | |
return this.rotation.eulerAngles; | |
} | |
set | |
{ | |
this.rotation = Quaternion.Euler(value); | |
} | |
} | |
/// <summary> | |
/// <para>The rotation as Euler angles in degrees relative to the parent transform's rotation.</para> | |
/// </summary> | |
public Vector3 localEulerAngles | |
{ | |
get | |
{ | |
return this.localRotation.eulerAngles; | |
} | |
set | |
{ | |
this.localRotation = Quaternion.Euler(value); | |
} | |
} | |
/// <summary> | |
/// <para>The red axis of the transform in world space.</para> | |
/// </summary> | |
public Vector3 right | |
{ | |
get | |
{ | |
return this.rotation * Vector3.right; | |
} | |
set | |
{ | |
this.rotation = Quaternion.FromToRotation(Vector3.right, value); | |
} | |
} | |
/// <summary> | |
/// <para>The green axis of the transform in world space.</para> | |
/// </summary> | |
public Vector3 up | |
{ | |
get | |
{ | |
return this.rotation * Vector3.up; | |
} | |
set | |
{ | |
this.rotation = Quaternion.FromToRotation(Vector3.up, value); | |
} | |
} | |
/// <summary> | |
/// <para>The blue axis of the transform in world space.</para> | |
/// </summary> | |
public Vector3 forward | |
{ | |
get | |
{ | |
return this.rotation * Vector3.forward; | |
} | |
set | |
{ | |
this.rotation = Quaternion.LookRotation(value); | |
} | |
} | |
/// <summary> | |
/// <para>The rotation of the transform in world space stored as a [[Quaternion]].</para> | |
/// </summary> | |
public Quaternion rotation | |
{ | |
get | |
{ | |
return unityEngineTransform.rotation; | |
} | |
set | |
{ | |
unityEngineTransform.rotation = value; | |
} | |
} | |
/// <summary> | |
/// <para>The rotation of the transform relative to the parent transform's rotation.</para> | |
/// </summary> | |
public Quaternion localRotation | |
{ | |
get | |
{ | |
return unityEngineTransform.localRotation; | |
} | |
set | |
{ | |
unityEngineTransform.localRotation = value; | |
} | |
} | |
/// <summary> | |
/// <para>The scale of the transform relative to the parent.</para> | |
/// </summary> | |
public Vector3 localScale | |
{ | |
get | |
{ | |
return unityEngineTransform.localScale; | |
} | |
set | |
{ | |
unityEngineTransform.localScale = value; | |
} | |
} | |
/// <summary> | |
/// <para>The parent of the transform.</para> | |
/// </summary> | |
public Transform parent | |
{ | |
get | |
{ | |
return unityEngineTransform.parent; | |
} | |
set | |
{ | |
unityEngineTransform.parent = value; | |
} | |
} | |
/// <summary> | |
/// <para>Matrix that transforms a point from world space into local space (RO).</para> | |
/// </summary> | |
public Matrix4x4 worldToLocalMatrix | |
{ | |
get | |
{ | |
return unityEngineTransform.worldToLocalMatrix; | |
} | |
} | |
/// <summary> | |
/// <para>Matrix that transforms a point from local space into world space (RO).</para> | |
/// </summary> | |
public Matrix4x4 localToWorldMatrix | |
{ | |
get | |
{ | |
return unityEngineTransform.localToWorldMatrix; | |
} | |
} | |
/// <summary> | |
/// <para>Returns the topmost transform in the hierarchy.</para> | |
/// </summary> | |
public Transform root | |
{ | |
get | |
{ | |
return unityEngineTransform.root; | |
} | |
} | |
/// <summary> | |
/// <para>The number of children the Transform has.</para> | |
/// </summary> | |
public int childCount | |
{ | |
get | |
{ | |
return unityEngineTransform.childCount; | |
} | |
} | |
/// <summary> | |
/// <para>The global scale of the object (RO).</para> | |
/// </summary> | |
public Vector3 lossyScale | |
{ | |
get | |
{ | |
return unityEngineTransform.lossyScale; | |
} | |
} | |
/// <summary> | |
/// <para>Has the transform changed since the last time the flag was set to 'false'?</para> | |
/// </summary> | |
public bool hasChanged | |
{ | |
get | |
{ | |
return unityEngineTransform.hasChanged; | |
} | |
set | |
{ | |
unityEngineTransform.hasChanged = value; | |
} | |
} | |
public void SetParent(Transform parent) | |
{ | |
this.SetParent(parent, true); | |
} | |
/// <summary> | |
/// <para>Set the parent of the transform.</para> | |
/// </summary> | |
/// <param name="parent">The parent Transform to use.</param> | |
/// <param name="worldPositionStays">If true, the parent-relative position, scale and rotation is modified such that the object keeps the same world space position, rotation and scale as before.</param> | |
public void SetParent(Transform parent, bool worldPositionStays) | |
{ | |
unityEngineTransform.SetParent(parent, worldPositionStays); | |
} | |
public void Translate(Vector3 translation) | |
{ | |
Space relativeTo = Space.Self; | |
this.Translate(translation, relativeTo); | |
} | |
/// <summary> | |
/// <para>Moves the transform in the direction and distance of /translation/.</para> | |
/// </summary> | |
/// <param name="translation"></param> | |
/// <param name="relativeTo"></param> | |
public void Translate(Vector3 translation, [DefaultValue("Space.Self")] Space relativeTo) | |
{ | |
if (relativeTo == Space.World) | |
{ | |
this.position += translation; | |
} | |
else | |
{ | |
this.position += this.TransformDirection(translation); | |
} | |
} | |
[ExcludeFromDocs] | |
public void Translate(float x, float y, float z) | |
{ | |
Space relativeTo = Space.Self; | |
this.Translate(x, y, z, relativeTo); | |
} | |
/// <summary> | |
/// <para>Moves the transform by /x/ along the x axis, /y/ along the y axis, and /z/ along the z axis.</para> | |
/// </summary> | |
/// <param name="x"></param> | |
/// <param name="y"></param> | |
/// <param name="z"></param> | |
/// <param name="relativeTo"></param> | |
public void Translate(float x, float y, float z, [DefaultValue("Space.Self")] Space relativeTo) | |
{ | |
this.Translate(new Vector3(x, y, z), relativeTo); | |
} | |
/// <summary> | |
/// <para>Moves the transform in the direction and distance of /translation/.</para> | |
/// </summary> | |
/// <param name="translation"></param> | |
/// <param name="relativeTo"></param> | |
public void Translate(Vector3 translation, Transform relativeTo) | |
{ | |
if (relativeTo) | |
{ | |
this.position += relativeTo.TransformDirection(translation); | |
} | |
else | |
{ | |
this.position += translation; | |
} | |
} | |
/// <summary> | |
/// <para>Moves the transform by /x/ along the x axis, /y/ along the y axis, and /z/ along the z axis.</para> | |
/// </summary> | |
/// <param name="x"></param> | |
/// <param name="y"></param> | |
/// <param name="z"></param> | |
/// <param name="relativeTo"></param> | |
public void Translate(float x, float y, float z, Transform relativeTo) | |
{ | |
this.Translate(new Vector3(x, y, z), relativeTo); | |
} | |
[ExcludeFromDocs] | |
public void Rotate(Vector3 eulerAngles) | |
{ | |
Space relativeTo = Space.Self; | |
this.Rotate(eulerAngles, relativeTo); | |
} | |
/// <summary> | |
/// <para>Applies a rotation of /eulerAngles.z/ degrees around the z axis, /eulerAngles.x/ degrees around the x axis, and /eulerAngles.y/ degrees around the y axis (in that order).</para> | |
/// </summary> | |
/// <param name="eulerAngles"></param> | |
/// <param name="relativeTo"></param> | |
public void Rotate(Vector3 eulerAngles, [DefaultValue("Space.Self")] Space relativeTo) | |
{ | |
Quaternion rhs = Quaternion.Euler(eulerAngles.x, eulerAngles.y, eulerAngles.z); | |
if (relativeTo == Space.Self) | |
{ | |
this.localRotation *= rhs; | |
} | |
else | |
{ | |
this.rotation *= Quaternion.Inverse(this.rotation) * rhs * this.rotation; | |
} | |
} | |
[ExcludeFromDocs] | |
public void Rotate(float xAngle, float yAngle, float zAngle) | |
{ | |
Space relativeTo = Space.Self; | |
this.Rotate(xAngle, yAngle, zAngle, relativeTo); | |
} | |
/// <summary> | |
/// <para>Applies a rotation of /zAngle/ degrees around the z axis, /xAngle/ degrees around the x axis, and /yAngle/ degrees around the y axis (in that order).</para> | |
/// </summary> | |
/// <param name="xAngle"></param> | |
/// <param name="yAngle"></param> | |
/// <param name="zAngle"></param> | |
/// <param name="relativeTo"></param> | |
public void Rotate(float xAngle, float yAngle, float zAngle, [DefaultValue("Space.Self")] Space relativeTo) | |
{ | |
this.Rotate(new Vector3(xAngle, yAngle, zAngle), relativeTo); | |
} | |
internal void RotateAroundInternal(Vector3 axis, float angle) | |
{ | |
// Transform.INTERNAL_CALL_RotateAroundInternal(this, ref axis, angle); | |
this.rotation *= Quaternion.AngleAxis(angle, axis); | |
} | |
[ExcludeFromDocs] | |
public void Rotate(Vector3 axis, float angle) | |
{ | |
Space relativeTo = Space.Self; | |
this.Rotate(axis, angle, relativeTo); | |
} | |
/// <summary> | |
/// <para>Rotates the transform around /axis/ by /angle/ degrees.</para> | |
/// </summary> | |
/// <param name="axis"></param> | |
/// <param name="angle"></param> | |
/// <param name="relativeTo"></param> | |
public void Rotate(Vector3 axis, float angle, [DefaultValue("Space.Self")] Space relativeTo) | |
{ | |
if (relativeTo == Space.Self) | |
{ | |
this.RotateAroundInternal(this.TransformDirection(axis), angle * 0.0174532924f); | |
} | |
else | |
{ | |
this.RotateAroundInternal(axis, angle * 0.0174532924f); | |
} | |
} | |
/// <summary> | |
/// <para>Rotates the transform about /axis/ passing through /point/ in world coordinates by /angle/ degrees.</para> | |
/// </summary> | |
/// <param name="point"></param> | |
/// <param name="axis"></param> | |
/// <param name="angle"></param> | |
public void RotateAround(Vector3 point, Vector3 axis, float angle) | |
{ | |
Vector3 vector = this.position; | |
Quaternion rotation = Quaternion.AngleAxis(angle, axis); | |
Vector3 vector2 = vector - point; | |
vector2 = rotation * vector2; | |
vector = point + vector2; | |
this.position = vector; | |
this.RotateAroundInternal(axis, angle * 0.0174532924f); | |
} | |
[ExcludeFromDocs] | |
public void LookAt(Transform target) | |
{ | |
Vector3 up = Vector3.up; | |
this.LookAt(target, up); | |
} | |
/// <summary> | |
/// <para>Rotates the transform so the forward vector points at /target/'s current position.</para> | |
/// </summary> | |
/// <param name="target">Object to point towards.</param> | |
/// <param name="worldUp">Vector specifying the upward direction.</param> | |
public void LookAt(Transform target, [DefaultValue("Vector3d.up")] Vector3 worldUp) | |
{ | |
if (target) | |
{ | |
this.LookAt(target.position, worldUp); | |
} | |
} | |
/// <summary> | |
/// <para>Rotates the transform so the forward vector points at /worldPosition/.</para> | |
/// </summary> | |
/// <param name="worldPosition">Point to look at.</param> | |
/// <param name="worldUp">Vector specifying the upward direction.</param> | |
public void LookAt(Vector3 worldPosition, [DefaultValue("Vector3d.up")] Vector3 worldUp) | |
{ | |
this.rotation = Quaternion.LookRotation(this.position - worldPosition, worldUp); | |
} | |
[ExcludeFromDocs] | |
public void LookAt(Vector3 worldPosition) | |
{ | |
Vector3 up = Vector3.up; | |
this.rotation = Quaternion.LookRotation(this.position - worldPosition, up); | |
} | |
/// <summary> | |
/// <para>Transforms /direction/ from local space to world space.</para> | |
/// </summary> | |
/// <param name="direction"></param> | |
public Vector3 TransformDirection(Vector3 direction) | |
{ | |
return unityEngineTransform.TransformDirection(direction); | |
} | |
/// <summary> | |
/// <para>Transforms direction /x/, /y/, /z/ from local space to world space.</para> | |
/// </summary> | |
/// <param name="x"></param> | |
/// <param name="y"></param> | |
/// <param name="z"></param> | |
public Vector3 TransformDirection(float x, float y, float z) | |
{ | |
return this.TransformDirection(new Vector3(x, y, z)); | |
} | |
/// <summary> | |
/// <para>Transforms a /direction/ from world space to local space. The opposite of Transform.TransformDirection.</para> | |
/// </summary> | |
/// <param name="direction"></param> | |
public Vector3 InverseTransformDirection(Vector3 direction) | |
{ | |
return unityEngineTransform.InverseTransformDirection(direction); | |
} | |
public Vector3 InverseTransformDirection(float x, float y, float z) | |
{ | |
return this.InverseTransformDirection(new Vector3(x, y, z)); | |
} | |
/// <summary> | |
/// <para>Transforms /vector/ from local space to world space.</para> | |
/// </summary> | |
/// <param name="vector"></param> | |
public Vector3 TransformVector(Vector3 vector) | |
{ | |
return unityEngineTransform.TransformVector(vector); | |
} | |
/// <summary> | |
/// <para>Transforms vector /x/, /y/, /z/ from local space to world space.</para> | |
/// </summary> | |
/// <param name="x"></param> | |
/// <param name="y"></param> | |
/// <param name="z"></param> | |
public Vector3 TransformVector(float x, float y, float z) | |
{ | |
return this.TransformVector(new Vector3(x, y, z)); | |
} | |
/// <summary> | |
/// <para>Transforms a /vector/ from world space to local space. The opposite of Transform.TransformVector.</para> | |
/// </summary> | |
/// <param name="vector"></param> | |
public Vector3 InverseTransformVector(Vector3 vector) | |
{ | |
return unityEngineTransform.InverseTransformVector(vector); | |
} | |
/// <summary> | |
/// <para>Transforms the vector /x/, /y/, /z/ from world space to local space. The opposite of Transform.TransformVector.</para> | |
/// </summary> | |
/// <param name="x"></param> | |
/// <param name="y"></param> | |
/// <param name="z"></param> | |
public Vector3 InverseTransformVector(float x, float y, float z) | |
{ | |
return this.InverseTransformVector(new Vector3(x, y, z)); | |
} | |
/// <summary> | |
/// <para>Transforms /position/ from local space to world space.</para> | |
/// </summary> | |
/// <param name="position"></param> | |
public Vector3 TransformPoint(Vector3 position) | |
{ | |
return unityEngineTransform.TransformPoint(position); | |
} | |
/// <summary> | |
/// <para>Transforms the position /x/, /y/, /z/ from local space to world space.</para> | |
/// </summary> | |
/// <param name="x"></param> | |
/// <param name="y"></param> | |
/// <param name="z"></param> | |
public Vector3 TransformPoint(float x, float y, float z) | |
{ | |
return this.TransformPoint(new Vector3(x, y, z)); | |
} | |
/// <summary> | |
/// <para>Transforms /position/ from world space to local space.</para> | |
/// </summary> | |
/// <param name="position"></param> | |
public Vector3 InverseTransformPoint(Vector3 position) | |
{ | |
return unityEngineTransform.InverseTransformPoint(position); | |
} | |
/// <summary> | |
/// <para>Transforms the position /x/, /y/, /z/ from world space to local space. The opposite of Transform.TransformPoint.</para> | |
/// </summary> | |
/// <param name="x"></param> | |
/// <param name="y"></param> | |
/// <param name="z"></param> | |
public Vector3 InverseTransformPoint(float x, float y, float z) | |
{ | |
return this.InverseTransformPoint(new Vector3(x, y, z)); | |
} | |
/// <summary> | |
/// <para>Unparents all children.</para> | |
/// </summary> | |
public void DetachChildren() | |
{ | |
unityEngineTransform.DetachChildren(); | |
} | |
/// <summary> | |
/// <para>Move the transform to the start of the local transform list.</para> | |
/// </summary> | |
public void SetAsFirstSibling() | |
{ | |
unityEngineTransform.SetAsFirstSibling(); | |
} | |
/// <summary> | |
/// <para>Move the transform to the end of the local transform list.</para> | |
/// </summary> | |
public void SetAsLastSibling() | |
{ | |
unityEngineTransform.SetAsLastSibling(); | |
} | |
/// <summary> | |
/// <para>Sets the sibling index.</para> | |
/// </summary> | |
/// <param name="index">Index to set.</param> | |
public void SetSiblingIndex(int index) | |
{ | |
unityEngineTransform.SetSiblingIndex(index); | |
} | |
/// <summary> | |
/// <para>Gets the sibling index.</para> | |
/// </summary> | |
public int GetSiblingIndex() | |
{ | |
return unityEngineTransform.GetSiblingIndex(); | |
} | |
/// <summary> | |
/// <para>Finds a child by /name/ and returns it.</para> | |
/// </summary> | |
/// <param name="name">Name of child to be found.</param> | |
public Transform Find(string name) | |
{ | |
return unityEngineTransform.Find(name); | |
} | |
/// <summary> | |
/// <para>Is this transform a child of /parent/?</para> | |
/// </summary> | |
/// <param name="parent"></param> | |
public bool IsChildOf(Transform parent) | |
{ | |
return unityEngineTransform.IsChildOf(parent); | |
} | |
public Transform FindChild(string name) | |
{ | |
return this.Find(name); | |
} | |
public IEnumerator GetEnumerator() | |
{ | |
return new Enumerator(this); | |
} | |
IEnumerator<Transform> IEnumerable<Transform>.GetEnumerator() | |
{ | |
return new Enumerator(this); | |
} | |
/// <summary> | |
/// <para></para> | |
/// </summary> | |
/// <param name="axis"></param> | |
/// <param name="angle"></param> | |
[Obsolete("use Transform.Rotate instead.")] | |
public void RotateAround(Vector3 axis, float angle) | |
{ | |
unityEngineTransform.RotateAround(axis, angle); | |
} | |
[Obsolete("use Transform.Rotate instead.")] | |
public void RotateAroundLocal(Vector3 axis, float angle) | |
{ | |
unityEngineTransform.RotateAroundLocal(axis, angle); | |
} | |
/// <summary> | |
/// <para>Returns a transform child by index.</para> | |
/// </summary> | |
/// <param name="index">Index of the child transform to return. Must be smaller than Transform.childCount.</param> | |
/// <returns> | |
/// <para>Transform child by index.</para> | |
/// </returns> | |
public Transform GetChild(int index) | |
{ | |
return unityEngineTransform.GetChild(index); | |
} | |
[Obsolete("use Transform.childCount instead.")] | |
public int GetChildCount() | |
{ | |
return unityEngineTransform.GetChildCount(); | |
} | |
UnityEngine.Transform unityEngineTransform; | |
public static implicit operator UnityEngine.Transform(Transform me) | |
{ | |
return me.unityEngineTransform; | |
} | |
public static implicit operator Transform(UnityEngine.Transform other) | |
{ | |
Transform result; | |
if (!unityEngineTransformToMyTransform.TryGetValue(other, out result)) | |
{ | |
if (other.root == other) result = new TransformRoot() { unityEngineTransform = other, gameObject = other.gameObject }; | |
else result = new TransformChild() { unityEngineTransform = other, gameObject = other.gameObject }; | |
unityEngineTransformToMyTransform[other] = result; | |
} | |
return result; | |
} | |
static Dictionary<UnityEngine.Transform, Transform> unityEngineTransformToMyTransform = new Dictionary<UnityEngine.Transform, Transform>(); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using UnityEngine; | |
using Manager; | |
public class TransformChild : Transform | |
{ | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using UnityEngine; | |
public enum TransformFollowType | |
{ | |
None = 0, | |
Position = 1 << 1, | |
Rotation = 1 << 2, | |
PositionAndRotation = 1 << 1 | 1 << 2, | |
Physical = 1 << 3, | |
} | |
/// <summary> | |
/// Transform that reperesents the root of the GameObject. | |
/// Support following other Transforms. | |
/// Builds a chain of follow and ignores collision between all colliders in this chain. | |
/// </summary> | |
public class TransformRoot : Transform | |
{ | |
struct FollowData | |
{ | |
public Transform parent; | |
public TransformRoot child; | |
public Vector3 posOffset; | |
public Quaternion rotOffset; | |
public TransformFollowType followType; | |
//public Transform jointTarget; | |
//public Joint joint; | |
} | |
FollowData followData; | |
Rigidbody rigidbody { get { return this.gameObject.GetComponent<Rigidbody>(); } } | |
public void Throw(Vector3 velocityChange) | |
{ | |
StopFollowing(); | |
if (rigidbody) | |
rigidbody.AddForce(velocityChange, ForceMode.VelocityChange); | |
} | |
public void Follow(Transform parent, Vector3 posOffset = default(Vector3), Quaternion rotOffset = default(Quaternion), TransformFollowType followType = TransformFollowType.PositionAndRotation) | |
{ | |
if (rotOffset.x == 0 && rotOffset.y == 0 && rotOffset.z == 0 && rotOffset.z == 0) rotOffset = Quaternion.identity; | |
followData.parent = parent; | |
followData.posOffset = posOffset; | |
followData.rotOffset = rotOffset; | |
followData.followType = followType; | |
if (followData.parent) ((TransformRoot)followData.parent).IgnoreCollisionWithChild(this, true); | |
} | |
/* | |
// TODO: TOFIX | |
public void FollowPhysical(TransformRoot child, Transform parent, Vector3 posOffset = default(Vector3), Quaternion rotOffset = default(Quaternion)) | |
{ | |
StopFollowing(); | |
if (child == null || parent == null) throw new System.NullReferenceException("child or parent"); | |
var joint = child.gameObject.AddComponent<SpringJoint>(); | |
joint.spring = 1000000; | |
joint.damper = 0; | |
joint.minDistance = 0; | |
joint.maxDistance = 0.5f; | |
var jointTarget = (new GameObject("Physical Follow Joint Target '" + child.name + "' to '" + parent.name + "'")).transform; | |
var rb = jointTarget.gameObject.AddComponent<Rigidbody>(); | |
rb.isKinematic = true; | |
jointTarget.position = child.position; | |
joint.connectedBody = rb; | |
followData.Add(child, new FollowData() | |
{ | |
parent = parent, | |
child = jointTarget, | |
posOffset = posOffset, | |
rotOffset = rotOffset, | |
followType = TransformFollowType.Physical, | |
jointTarget = jointTarget, | |
joint = joint | |
}); | |
} | |
*/ | |
public void StopFollowing() | |
{ | |
if (followData.parent) | |
{ | |
var parentTransformRoot = ((TransformRoot)followData.parent); | |
parentTransformRoot.IgnoreCollisionWithChild(this, false); | |
foreach (var follower in followChain) | |
{ | |
parentTransformRoot.IgnoreCollisionWithChild(follower, false); | |
} | |
followChain.Clear(); | |
} | |
followData.followType = TransformFollowType.None; | |
followData.parent = null; | |
} | |
List<TransformRoot> followChain = new List<TransformRoot>(); | |
void IgnoreCollisionWithChild(TransformRoot child, bool ignore) | |
{ | |
if (ignore) followChain.Add(child); | |
else followChain.Remove(child); | |
IgnoreCollision(this, child, ignore); | |
if (followData.parent) ((TransformRoot)followData.parent).IgnoreCollisionWithChild(child, ignore); | |
} | |
public bool IsFollowingAnyone() | |
{ | |
return followData.parent != null; | |
} | |
public bool IsFollowing(Transform parent) | |
{ | |
return parent == followData.parent; | |
} | |
static void IgnoreCollision(Transform go1, Transform go2, bool ignore) | |
{ | |
go1 = go1.root; | |
go2 = go2.root; | |
var lc1 = go1.gameObject.GetComponentsInChildren<Collider>(); | |
var lc2 = go2.gameObject.GetComponentsInChildren<Collider>(); | |
foreach (var c1 in lc1) | |
{ | |
if (c1.gameObject.activeInHierarchy && c1.enabled) | |
{ | |
foreach (var c2 in lc2) | |
{ | |
if (c2.gameObject.activeInHierarchy && c2.enabled) | |
{ | |
Physics.IgnoreCollision(c1, c2, ignore); | |
} | |
} | |
} | |
} | |
} | |
void Update() | |
{ | |
if (followData.parent) | |
{ | |
var me = this; | |
if ((followData.followType & TransformFollowType.Position) > 0) me.position = followData.parent.position + followData.posOffset; | |
if ((followData.followType & TransformFollowType.Rotation) > 0) me.rotation = (Quaternion)followData.parent.rotation * followData.rotOffset; | |
} | |
} | |
public static implicit operator TransformRoot(UnityEngine.Transform from) | |
{ | |
if (!from) throw new System.NullReferenceException("from"); | |
return (TransformRoot)((Transform)from); | |
} | |
} |
I used http://ilspy.net/ to see decompiled UnityEngine.Transform. The INTERNAL_CALL_ are methods which are implemented in C++ side of Unity engine. The Transfrom class here is just a wrapper to UnityEngine.Transform so I can implement my own IEnumerator and other stuff.
I guess you could implement those INTERNAL_CALL_ methods with
transform.localToWorldMatrix.MultiplyPoint
transform.localToWorldMatrix.MultiplyVector
transform.worldToLocalMatrix.MultiplyPoint
transform.worldToLocalMatrix.MultiplyVector
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Interesting insight about Unity's Transform implementation, thanks a lot. I currently try to learn from Unitys structure to prepare something like an own engine, or at least a re-implementation of Unity's most important classes (independed of Unity's classes or DLLs) done in double-precision instead of floats, which I then can run within Unity or maybe later Unity-independently in a custom implementation.
I am progressing pretty well with most of the stuff, however some things within the Transform bother me.
I wonder about your re-implementations of the INTERNAL_CALL classes
INTERNAL_CALL_TransformDirection
INTERNAL_CALL_InverseTransformDirection
INTERNAL_CALL_TransformVector
INTERNAL_CALL_InverseTransformVector
INTERNAL_CALL_TransformPoint
INTERNAL_CALL_InverseTransformPoint
as they almost do nothing than recalling the same function again. E.g. for TransformDirection. Looks way to simple. Am I missing something?
Or, which took over similar: