BearishSun 9 лет назад
Родитель
Сommit
7e42b18f96
29 измененных файлов с 1473 добавлено и 13 удалено
  1. 4 4
      BansheeCore/Include/BsBoxCollider.h
  2. 1 1
      BansheeCore/Include/BsCCollider.h
  3. 1 1
      BansheeCore/Include/BsCapsuleCollider.h
  4. 1 1
      BansheeCore/Source/BsCSphereCollider.cpp
  5. 17 2
      MBansheeEngine/MBansheeEngine.csproj
  6. 5 0
      MBansheeEngine/Math/Vector2.cs
  7. 5 0
      MBansheeEngine/Math/Vector3.cs
  8. 5 0
      MBansheeEngine/Math/Vector4.cs
  9. 69 0
      MBansheeEngine/Physics/BoxCollider.cs
  10. 118 0
      MBansheeEngine/Physics/CapsuleCollider.cs
  11. 470 0
      MBansheeEngine/Physics/Collider.cs
  12. 73 0
      MBansheeEngine/Physics/MeshCollider.cs
  13. 34 0
      MBansheeEngine/Physics/NativeBoxCollider.cs
  14. 46 0
      MBansheeEngine/Physics/NativeCapsuleCollider.cs
  15. 212 0
      MBansheeEngine/Physics/NativeCollider.cs
  16. 41 0
      MBansheeEngine/Physics/NativeMeshCollider.cs
  17. 22 0
      MBansheeEngine/Physics/NativePlaneCollider.cs
  18. 7 0
      MBansheeEngine/Physics/NativeRigidbody.cs
  19. 34 0
      MBansheeEngine/Physics/NativeSphereCollider.cs
  20. 135 0
      MBansheeEngine/Physics/PhysicsCommon.cs
  21. 0 0
      MBansheeEngine/Physics/PhysicsMaterial.cs
  22. 0 0
      MBansheeEngine/Physics/PhysicsMesh.cs
  23. 73 0
      MBansheeEngine/Physics/PlaneCollider.cs
  24. 7 0
      MBansheeEngine/Physics/Rigidbody.cs
  25. 69 0
      MBansheeEngine/Physics/SphereCollider.cs
  26. 9 0
      SBansheeEngine/Include/BsScriptCollider.h
  27. 2 2
      SBansheeEngine/Include/BsScriptCollisionData.h
  28. 2 2
      SBansheeEngine/Include/BsScriptPhysicsQueryHit.h
  29. 11 0
      SBansheeEngine/Source/BsScriptCollider.cpp

+ 4 - 4
BansheeCore/Include/BsBoxCollider.h

@@ -13,22 +13,22 @@ namespace BansheeEngine
 	 *  @{
 	 */
 
-	/** Collider with a box geometry. */
+	/** Collider with box geometry. */
 	class BS_CORE_EXPORT BoxCollider : public Collider
 	{
 	public:
 		BoxCollider();
 
-		/** Sets the extents of the geometry of the box. Extents are size/2. */
+		/** Sets the extents (half size) of the geometry of the box. */
 		virtual void setExtents(const Vector3& extents) = 0;
 
-		/** Gets the extents of the geometry of the box. Extents are size/2. */
+		/** Gets the extents (half size) of the geometry of the box. */
 		virtual Vector3 getExtents() const = 0;
 
 		/** 
 		 * Creates a new box collider. 
 		 *
-		 * @param[in]	extents		Extents of the box. Extents are size/2.
+		 * @param[in]	extents		Extents (half size) of the box.
 		 * @param[in]	position	Center of the box.
 		 * @param[in]	rotation	Rotation of the box.
 		 */

+ 1 - 1
BansheeCore/Include/BsCCollider.h

@@ -139,7 +139,7 @@ namespace BansheeEngine
 		void setRigidbody(const HRigidbody& rigidbody, bool internal = false);
 
 		/** 
-		 * Updates the transform of the internal Collider representation from the transform of the component's Scene Object.
+		 * Updates the transform of the internal Collider representation from the transform of the component's scene object.
 		 */
 		void updateTransform();
 

+ 1 - 1
BansheeCore/Include/BsCapsuleCollider.h

@@ -26,7 +26,7 @@ namespace BansheeEngine
 		virtual void setHalfHeight(float halfHeight) = 0;
 
 		/** 
-		 * Gets the half  height of the capsule, from the origin to one of the hemispherical centers, along the normal
+		 * Gets the half height of the capsule, from the origin to one of the hemispherical centers, along the normal
 		 * vector. 
 		 */
 		virtual float getHalfHeight() const = 0;

+ 1 - 1
BansheeCore/Source/BsCSphereCollider.cpp

@@ -10,7 +10,7 @@ namespace BansheeEngine
 	CSphereCollider::CSphereCollider(const HSceneObject& parent, float radius)
 		: CCollider(parent), mRadius(radius)
 	{
-		setName("BoxCollider");
+		setName("SphereCollider");
 	}
 
 	void CSphereCollider::setRadius(float radius)

+ 17 - 2
MBansheeEngine/MBansheeEngine.csproj

@@ -109,8 +109,23 @@
     <Compile Include="MeshData.cs" />
     <Compile Include="MissingComponent.cs" />
     <Compile Include="PathEx.cs" />
-    <Compile Include="PhysicsMaterial.cs" />
-    <Compile Include="PhysicsMesh.cs" />
+    <Compile Include="Physics\BoxCollider.cs" />
+    <Compile Include="Physics\CapsuleCollider.cs" />
+    <Compile Include="Physics\Collider.cs" />
+    <Compile Include="Physics\MeshCollider.cs" />
+    <Compile Include="Physics\NativeBoxCollider.cs" />
+    <Compile Include="Physics\NativeCapsuleCollider.cs" />
+    <Compile Include="Physics\NativeCollider.cs" />
+    <Compile Include="Physics\NativeMeshCollider.cs" />
+    <Compile Include="Physics\NativePlaneCollider.cs" />
+    <Compile Include="Physics\NativeRigidbody.cs" />
+    <Compile Include="Physics\NativeSphereCollider.cs" />
+    <Compile Include="Physics\PhysicsMaterial.cs" />
+    <Compile Include="Physics\PhysicsMesh.cs" />
+    <Compile Include="Physics\PhysicsCommon.cs" />
+    <Compile Include="Physics\PlaneCollider.cs" />
+    <Compile Include="Physics\Rigidbody.cs" />
+    <Compile Include="Physics\SphereCollider.cs" />
     <Compile Include="PixelData.cs" />
     <Compile Include="PixelUtility.cs" />
     <Compile Include="PlainText.cs" />

+ 5 - 0
MBansheeEngine/Math/Vector2.cs

@@ -114,6 +114,11 @@ namespace BansheeEngine
             return new Vector2(-v.x, -v.y);
         }
 
+        public static Vector2 operator *(Vector2 a, Vector2 b)
+        {
+            return new Vector2(a.x * b.x, a.y * b.y);
+        }
+
         public static Vector2 operator* (Vector2 v, float d)
         {
             return new Vector2(v.x * d, v.y * d);

+ 5 - 0
MBansheeEngine/Math/Vector3.cs

@@ -133,6 +133,11 @@ namespace BansheeEngine
             return new Vector3(-v.x, -v.y, -v.z);
         }
 
+        public static Vector3 operator*(Vector3 a, Vector3 b)
+        {
+            return new Vector3(a.x * b.x, a.y * b.y, a.z * b.z);
+        }
+
         public static Vector3 operator* (Vector3 v, float d)
         {
             return new Vector3(v.x * d, v.y * d, v.z * d);

+ 5 - 0
MBansheeEngine/Math/Vector4.cs

@@ -141,6 +141,11 @@ namespace BansheeEngine
             return new Vector4(-v.x, -v.y, -v.z, -v.w);
         }
 
+        public static Vector4 operator *(Vector4 a, Vector4 b)
+        {
+            return new Vector4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
+        }
+
         public static Vector4 operator* (Vector4 v, float d)
         {
             return new Vector4(v.x * d, v.y * d, v.z * d, v.w * d);

+ 69 - 0
MBansheeEngine/Physics/BoxCollider.cs

@@ -0,0 +1,69 @@
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Collider with box geometry.
+    /// </summary>
+    public sealed class BoxCollider : Collider
+    {
+        [SerializeField]
+        private Vector3 extents = Vector3.One;
+
+        /// <summary>
+        /// Extents (half size) of the geometry of the box.
+        /// </summary>
+        public Vector3 Extents
+        {
+            get { return extents; }
+            set
+            {
+                if (extents == value)
+                    return;
+
+                extents = value;
+
+                if (Native != null)
+                {
+                    Native.Extents = value;
+
+                    if (parent != null)
+                        parent.UpdateMassDistribution();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Position of the box shape, relative to the component's scene object.
+        /// </summary>
+        public Vector3 Center
+        {
+            get { return serializableData.localPosition; }
+            set
+            {
+                if (serializableData.localPosition == value)
+                    return;
+
+                serializableData.localPosition = value;
+
+                if (Native != null)
+                    UpdateTransform();
+            }
+        }
+
+        /// <summary>
+        /// Returns the native box collider wrapped by this component.
+        /// </summary>
+        private NativeBoxCollider Native
+        {
+            get { return (NativeBoxCollider)native; }
+        }
+
+        /// <inheritdoc/>
+        internal override NativeCollider CreateCollider()
+        {
+            NativeBoxCollider boxCollider = new NativeBoxCollider();
+            boxCollider.Extents = extents;
+
+            return boxCollider;
+        }
+    }
+}

+ 118 - 0
MBansheeEngine/Physics/CapsuleCollider.cs

@@ -0,0 +1,118 @@
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Collider with capsule geometry.
+    /// </summary>
+    public sealed class CapsuleCollider : Collider
+    {
+        [SerializeField]
+        private float radius = 0.2f;
+
+        [SerializeField]
+        private float halfHeight = 0.5f;
+
+        [SerializeField]
+        private Vector3 normal = Vector3.YAxis;
+
+        /// <summary>
+        /// Radius of the capsule.
+        /// </summary>
+        public float Radius
+        {
+            get { return radius; }
+            set
+            {
+                if (radius == value)
+                    return;
+
+                radius = value;
+
+                if (Native != null)
+                {
+                    Native.Radius = value;
+
+                    if (parent != null)
+                        parent.UpdateMassDistribution();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Half height of the capsule, from the origin to one of the hemispherical centers, along the normal vector.
+        /// </summary>
+        public float HalfHeight
+        {
+            get { return halfHeight; }
+            set
+            {
+                if (halfHeight == value)
+                    return;
+
+                halfHeight = value;
+
+                if (Native != null)
+                {
+                    Native.HalfHeight = value;
+
+                    if (parent != null)
+                        parent.UpdateMassDistribution();
+                }
+            }
+        }
+        
+        /// <summary>
+        /// Position of the capsule shape, relative to the component's scene object.
+        /// </summary>
+        public Vector3 Center
+        {
+            get { return serializableData.localPosition; }
+            set
+            {
+                if (serializableData.localPosition == value)
+                    return;
+
+                serializableData.localPosition = value;
+
+                if (Native != null)
+                    UpdateTransform();
+            }
+        }
+
+        /// <summary>
+        /// Normal vector of the capsule. It determines how is the capsule oriented.
+        /// </summary>
+        public Vector3 Normal
+        {
+            get { return normal; }
+            set
+            {
+                if (normal == value)
+                    return;
+
+                normal = value.Normalized;
+                serializableData.localRotation = Quaternion.FromToRotation(Vector3.XAxis, normal);
+
+                if (Native != null)
+                    UpdateTransform();
+            }
+        }
+
+        /// <summary>
+        /// Returns the native capsule collider wrapped by this component.
+        /// </summary>
+        private NativeCapsuleCollider Native
+        {
+            get { return (NativeCapsuleCollider)native; }
+        }
+
+        /// <inheritdoc/>
+        internal override NativeCollider CreateCollider()
+        {
+            NativeCapsuleCollider capsuleCollider = new NativeCapsuleCollider();
+            capsuleCollider.Radius = radius;
+            capsuleCollider.HalfHeight = halfHeight;
+
+            return capsuleCollider;
+        }
+    }
+}

+ 470 - 0
MBansheeEngine/Physics/Collider.cs

@@ -0,0 +1,470 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Collider represents physics geometry that can be in multiple states:
+    ///  - Default: Static geometry that physics objects can collide with.
+    ///  - Trigger: Static geometry that can't be collided with but will report touch events.
+    ///  - Dynamic: Dynamic geometry that is a part of a Rigidbody.A set of colliders defines the shape of the parent 
+    ///             rigidbody.
+    /// </summary>
+    public abstract class Collider : Component
+    {
+        internal NativeCollider native;
+        protected Rigidbody parent;
+
+        [SerializeField]
+        internal SerializableData serializableData = new SerializableData();
+
+        /// <summary>
+        /// Triggered when some object starts interacting with the collider. Only triggered if proper collision report mode
+        /// is turned on.
+        /// </summary>
+        public event Action<CollisionData> OnCollisionBegin;
+
+        /// <summary>
+        /// Triggered for every frame that an object remains interacting with a collider. Only triggered if proper collision
+        /// report mode is turned on.
+        /// </summary>
+        public event Action<CollisionData> OnCollisionStay;
+
+        /// <summary>
+        /// Triggered when some object stops interacting with the collider. Only triggered if proper collision report mode
+        /// is turned on.
+        /// </summary>
+        public event Action<CollisionData> OnCollisionEnd;
+
+        /// <summary>
+        /// Determines how the collider used. A trigger will not be used for collisions (i.e. objects will pass through it),
+        /// but collision events will still be reported.
+        /// </summary>
+        public bool IsTrigger
+        {
+            get { return serializableData.isTrigger; }
+            set
+            {
+                if (serializableData.isTrigger == value)
+                    return;
+
+                serializableData.isTrigger = value;
+
+                if (native != null)
+                {
+                    native.IsTrigger = value;
+                    UpdateParentRigidbody();
+                    UpdateTransform();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Determines mass of the collider. Only relevant if the collider is part of a rigidbody. Ultimately this will 
+        /// determine the total mass, center of mass and inertia tensors of the parent rigidbody(if they're being calculated
+        /// automatically).
+        /// </summary>
+        public float Mass
+        {
+            get { return serializableData.mass; }
+            set
+            {
+                if (serializableData.mass == value)
+                    return;
+
+                serializableData.mass = value;
+
+                if (native != null)
+                {
+                    native.Mass = value;
+
+                    if (parent != null)
+                        parent.UpdateMassDistribution();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Physics material that determines how objects hitting the collider behave.
+        /// </summary>
+        public PhysicsMaterial Material
+        {
+            get { return serializableData.material; }
+            set
+            {
+                serializableData.material = value;
+
+                if (native != null)
+                    native.Material = value;
+            }
+        }
+
+        /// <summary>
+        /// Determines how far apart do two shapes need to be away from each other before the physics runtime starts 
+        /// generating repelling impulse for them.This distance will be the sum of contact offsets of the two interacting
+        /// objects.If objects are moving fast you can increase this value to start generating the impulse earlier and 
+        /// potentially prevent the objects from interpenetrating. This value is in meters.
+        /// </summary>
+        public float ContactOffset
+        {
+            get { return serializableData.contactOffset; }
+            set
+            {
+                serializableData.contactOffset = value;
+
+                if (native != null)
+                    native.ContactOffset = value;
+            }
+        }
+
+        /// <summary>
+        /// Determines at what distance should two objects resting on one another come to an equilibrium. The value used in the
+        /// runtime will be the sum of rest offsets for both interacting objects. This value is in meters.
+        /// </summary>
+        public float RestOffset
+        {
+            get { return serializableData.restOffset; }
+            set
+            {
+                serializableData.restOffset = value;
+
+                if (native != null)
+                    native.RestOffset = value;
+            }
+        }
+
+        /// <summary>
+        /// Determines with which objects will the collider collide. Objects that are allowed to collide with this
+        /// object must have the same bits set in their own layers.
+        /// </summary>
+        public ulong Layer
+        {
+            get { return serializableData.layer; }
+            set
+            {
+                serializableData.layer = value;
+
+                if (native != null)
+                    native.Layer = value;
+            }
+        }
+
+        /// <summary>
+        /// Determines which (if any) collision events are reported.
+        /// </summary>
+        public CollisionReportMode CollisionReportMode
+        {
+            get { return serializableData.collisionReportMode; }
+            set
+            {
+                serializableData.collisionReportMode = value;
+
+                if (native != null)
+                    UpdateCollisionReportMode();
+            }
+        }
+
+        /// <summary>
+        /// Checks does the ray hit this collider. 
+        /// </summary>
+        /// <param name="ray">Ray to check.</param>
+        /// <param name="hit">Information about the hit. Valid only if the method returns true.</param>
+        /// <param name="maxDist">Maximum distance from the ray origin to search for hits.</param>
+        /// <returns>True if the ray has hit the collider.</returns>
+        public bool Raycast(Ray ray, out PhysicsQueryHit hit, float maxDist)
+        {
+            return Raycast(ray.origin, ray.direction, out hit, maxDist);
+        }
+
+        /// <summary>
+        /// Checks does the ray hit this collider. 
+        /// </summary>
+        /// <param name="origin">Origin of the ray to check.</param>
+        /// <param name="unitDir">Unit direction of the ray to check.</param>
+        /// <param name="hit">Information about the hit. Valid only if the method returns true.</param>
+        /// <param name="maxDist">Maximum distance from the ray origin to search for hits.</param>
+        /// <returns>True if the ray has hit the collider.</returns>
+        public bool Raycast(Vector3 origin, Vector3 unitDir, out PhysicsQueryHit hit, float maxDist)
+        {
+            hit = new PhysicsQueryHit();
+
+            if (native == null)
+                return false;
+
+            ScriptPhysicsQueryHit scriptHit;
+            bool wasHit = native.Raycast(origin, unitDir, out scriptHit, maxDist);
+
+            hit.collider = scriptHit.collider.Component;
+            hit.distance = scriptHit.distance;
+            hit.normal = scriptHit.normal;
+            hit.point = scriptHit.point;
+            hit.triangleIdx = scriptHit.triangleIdx;
+            hit.uv = scriptHit.uv;
+
+            return wasHit;
+        }
+
+        /// <summary>
+        /// Creates an internal instance of the collider. Should be overriden by specific collider implementations.
+        /// </summary>
+        /// <returns>An instance of a specific internal collider implementation. </returns>
+        internal abstract NativeCollider CreateCollider();
+
+        /// <summary>
+        /// Changes the rigidbody parent of the collider. Meant to be called from the Rigidbody itself. 
+        /// </summary>
+        /// <param name="rigidbody">New rigidbody to assign as the parent to the collider.</param>
+        /// <param name="isInternal">If true the rigidbody will just be changed internally, but parent rigidbody will not be
+        ///                          notified.</param>
+        internal void SetRigidbody(Rigidbody rigidbody, bool isInternal = false)
+	    {
+		    if (rigidbody == parent)
+			    return;
+
+		    if (native != null && !isInternal)
+		    {
+			    if (parent != null)
+                    parent.RemoveCollider(this);
+
+			    NativeRigidbody nativeRigidbody = null;
+
+			    if (rigidbody != null)
+                    nativeRigidbody = rigidbody.Native;
+
+		        native.Rigidbody = nativeRigidbody;;
+
+			    if (rigidbody != null)
+				    rigidbody.AddCollider(this);
+		    }
+
+		    parent = rigidbody;
+		    UpdateCollisionReportMode();
+	    }
+
+        /// <summary>
+        /// Triggered when the internal collider begins touching another object.
+        /// </summary>
+        /// <param name="data">Data about a collision.</param>
+        internal void DoOnCollisionBegin(CollisionData data)
+        {
+            if (OnCollisionBegin != null)
+                OnCollisionBegin(data);
+        }
+
+        /// <summary>
+        /// Triggered when the internal collider ends touching another object.
+        /// </summary>
+        /// <param name="data">Data about the collision.</param>
+        internal void DoOnCollisionStay(CollisionData data)
+        {
+            if (OnCollisionStay != null)
+                OnCollisionStay(data);
+        }
+
+        /// <summary>
+        /// Triggered when the internal collider ends touching another object.
+        /// </summary>
+        /// <param name="data">Data about the collision.</param>
+        internal void DoOnCollisionEnd(CollisionData data)
+        {
+            if (OnCollisionEnd != null)
+                OnCollisionEnd(data);
+        }
+
+        /// <summary>
+        /// Checks is the provided rigidbody a valid parent for this collider.
+        /// 
+        /// This is required because certain colliders are limited in how they can be used.
+        /// </summary>
+        /// <param name="parent">Rigidbody that is the potential parent.</param>
+        /// <returns>True if collider can be a part of the rigidbody.</returns>
+        protected virtual bool IsValidParent(Rigidbody parent)
+        {
+            return true;
+        }
+
+        /// <summary>
+        /// Searches the parent scene object hierarchy to find a parent Rigidbody component.
+        /// </summary>
+        protected void UpdateParentRigidbody()
+        {
+            if (serializableData.isTrigger)
+            {
+                SetRigidbody(null);
+                return;
+            }
+
+            SceneObject currentSO = SceneObject;
+            while (currentSO != null)
+            {
+                Rigidbody parent = currentSO.GetComponent<Rigidbody>();
+                if (parent != null)
+                {
+                    if (currentSO.Active && IsValidParent(parent))
+                        SetRigidbody(parent);
+                    else
+                        SetRigidbody(null);
+
+                    return;
+                }
+
+                currentSO = currentSO.Parent;
+            }
+
+            // Not found
+            SetRigidbody(null);
+        }
+
+        /// <summary>
+        /// Updates the transform of the internal Collider representation from the transform of the component's scene object.
+        /// </summary>
+        protected void UpdateTransform()
+        {
+            if (parent != null)
+            {
+                Vector3 parentPos = parent.SceneObject.Position;
+                Quaternion parentRot = parent.SceneObject.Rotation;
+
+                Vector3 myPos = SceneObject.Position;
+                Quaternion myRot = SceneObject.Rotation;
+
+                Vector3 scale = parent.SceneObject.Scale;
+                Vector3 invScale = scale;
+                if (invScale.x != 0) invScale.x = 1.0f / invScale.x;
+                if (invScale.y != 0) invScale.y = 1.0f / invScale.y;
+                if (invScale.z != 0) invScale.z = 1.0f / invScale.z;
+
+                Quaternion invRotation = parentRot.Inverse;
+
+                Vector3 relativePos = invRotation.Rotate(myPos - parentPos) * invScale;
+                Quaternion relativeRot = invRotation * myRot;
+
+                relativePos = relativePos + myRot.Rotate(serializableData.localPosition * scale);
+                relativeRot = relativeRot * serializableData.localRotation;
+
+                native.Position = relativePos;
+                native.Rotation = relativeRot;
+
+                parent.UpdateMassDistribution();
+            }
+            else
+            {
+                Vector3 myScale = SceneObject.Scale;
+                Quaternion myRot = SceneObject.Rotation;
+                Vector3 myPos = SceneObject.Position + myRot.Rotate(serializableData.localPosition * myScale);
+                myRot = myRot * serializableData.localRotation;
+
+                native.Position = myPos;
+                native.Rotation = myRot;
+            }
+        }
+
+        /// <summary>
+        /// Applies the collision report mode to the internal collider depending on the current state.
+        /// </summary>
+        protected void UpdateCollisionReportMode()
+        {
+            CollisionReportMode mode = serializableData.collisionReportMode;
+
+            if (parent != null)
+                mode = parent.CollisionReportMode;
+
+            native.CollisionReportMode = mode;
+        }
+
+        private void OnReset()
+        {
+            RestoreNative();
+        }
+
+        private void OnEnable()
+        {
+            if (native == null)
+                RestoreNative();
+        }
+
+        private void OnDisable()
+        {
+            DestroyNative();
+        }
+
+        private void OnDestroy()
+        {
+            DestroyNative();
+        }
+
+        private void OnTransformChanged(TransformChangedFlags flags)
+        {
+            if (!SceneObject.Active)
+                return;
+
+            if ((flags & TransformChangedFlags.Parent) != 0)
+                UpdateParentRigidbody();
+
+            // Don't update the transform if it's due to Physics update since then we can guarantee it will remain at the same
+            // relative transform to its parent
+            if (Physics.IsUpdateInProgress)
+                return;
+
+            if ((flags & (TransformChangedFlags.Parent | TransformChangedFlags.Transform)) != 0)
+                UpdateTransform();
+        }
+
+        /// <summary>
+        /// Destroys the internal collider representation.
+        /// </summary>
+        private void DestroyNative()
+        {
+            if (parent != null)
+                parent.RemoveCollider(this);
+
+            parent = null;
+
+            if (native != null)
+            {
+                native.Destroy();
+                native = null;
+            }
+        }
+
+        /// <summary>
+        /// Creates the internal representation of the Collider and restores the values saved by the Component.
+        /// </summary>
+        private void RestoreNative()
+        {
+            native = CreateCollider();
+
+            native.Component = this;
+            native.Position = serializableData.localPosition;
+            native.Rotation = serializableData.localRotation;
+            native.IsTrigger = serializableData.isTrigger;
+            native.Mass = serializableData.mass;
+            native.Material = serializableData.material;
+            native.ContactOffset = serializableData.contactOffset;
+            native.RestOffset = serializableData.restOffset;
+            native.Layer = serializableData.layer;
+
+            UpdateParentRigidbody();
+            UpdateTransform();
+            UpdateCollisionReportMode();
+        }
+
+        /// <summary>
+        /// Holds all data the collider component needs to persist through serialization.
+        /// </summary>
+        [SerializeObject]
+        internal class SerializableData
+        {
+            public Vector3 localPosition;
+            public Quaternion localRotation;
+            public bool isTrigger;
+            public float mass = 1.0f;
+            public PhysicsMaterial material;
+            public float contactOffset;
+            public float restOffset;
+            public ulong layer = 1;
+            public CollisionReportMode collisionReportMode = CollisionReportMode.None;
+        }
+    }
+}

+ 73 - 0
MBansheeEngine/Physics/MeshCollider.cs

@@ -0,0 +1,73 @@
+namespace BansheeEngine
+{
+    /// <summary>
+    /// A collider represented by an arbitrary mesh.
+    /// </summary>
+    public sealed class MeshCollider : Collider
+    {
+        [SerializeField]
+        private PhysicsMesh mesh;
+
+        /// <summary>
+        /// Mesh that represents the collider geometry. This can be a generic triangle mesh, or and convex mesh. Triangle
+        /// meshes are not supported as triggers, nor are they supported for colliders that are parts of a non-kinematic
+        /// rigidbody.
+        /// </summary>
+        public PhysicsMesh Mesh
+        {
+            get { return mesh; }
+            set
+            {
+                if (mesh == value)
+                    return;
+
+                if (IsTrigger && mesh.MeshType == PhysicsMeshType.Triangle)
+                {
+                    Debug.LogWarning("Triangle meshes are not supported on Trigger colliders.");
+                    return;
+                }
+
+                mesh = value;
+
+                if (Native != null)
+                {
+                    Native.Mesh = value;
+
+                    if (parent != null)
+                    {
+                        // If triangle mesh its possible the parent can no longer use this collider (they're not supported for 
+                        // non-kinematic rigidbodies)
+                        if (mesh != null && mesh.MeshType == PhysicsMeshType.Triangle)
+                            UpdateParentRigidbody();
+                        else
+                            parent.UpdateMassDistribution();
+                    }
+                }
+            }
+        }
+
+        /// <inheritdoc/>
+        protected override bool IsValidParent(Rigidbody parent) 
+	    {
+		    // Triangle mesh colliders cannot be used for non-kinematic rigidbodies
+		    return mesh == null|| mesh.MeshType == PhysicsMeshType.Convex || parent.IsKinematic;
+        }
+
+    /// <summary>
+    /// Returns the native mesh collider wrapped by this component.
+    /// </summary>
+    private NativeMeshCollider Native
+        {
+            get { return (NativeMeshCollider)native; }
+        }
+
+        /// <inheritdoc/>
+        internal override NativeCollider CreateCollider()
+        {
+            NativeMeshCollider meshCollider = new NativeMeshCollider();
+            meshCollider.Mesh = mesh;
+
+            return meshCollider;
+        }
+    }
+}

+ 34 - 0
MBansheeEngine/Physics/NativeBoxCollider.cs

@@ -0,0 +1,34 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Runtime.CompilerServices;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Wrapper around the native BoxCollider class.
+    /// <see cref="BoxCollider"/>
+    /// </summary>
+    internal class NativeBoxCollider : NativeCollider
+    {
+        public NativeBoxCollider()
+        {
+            Internal_CreateInstance(this);
+        }
+
+        public Vector3 Extents
+        {
+            get { Vector3 extents; Internal_GetExtents(mCachedPtr, out extents); return extents; }
+            set { Internal_SetExtents(mCachedPtr, ref value); }
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateInstance(NativeBoxCollider instance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetExtents(IntPtr thisPtr, ref Vector3 extents);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetExtents(IntPtr thisPtr, out Vector3 extents);
+    }
+}

+ 46 - 0
MBansheeEngine/Physics/NativeCapsuleCollider.cs

@@ -0,0 +1,46 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Runtime.CompilerServices;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Wrapper around the native CapsuleCollider class.
+    /// <see cref="CapsuleCollider"/>
+    /// </summary>
+    internal class NativeCapsuleCollider : NativeCollider
+    {
+        public NativeCapsuleCollider()
+        {
+            Internal_CreateInstance(this);
+        }
+
+        public float Radius
+        {
+            get { return Internal_GetRadius(mCachedPtr); }
+            set { Internal_SetRadius(mCachedPtr, value); }
+        }
+
+        public float HalfHeight
+        {
+            get { return Internal_GetHalfHeight(mCachedPtr); }
+            set { Internal_SetHalfHeight(mCachedPtr, value); }
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateInstance(NativeCapsuleCollider instance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern float Internal_GetHalfHeight(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetHalfHeight(IntPtr thisPtr, float radius);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern float Internal_GetRadius(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetRadius(IntPtr thisPtr, float radius);
+    }
+}

+ 212 - 0
MBansheeEngine/Physics/NativeCollider.cs

@@ -0,0 +1,212 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Runtime.CompilerServices;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Wrapper around the native Collider class.
+    /// <see cref="Collider"/>
+    /// </summary>
+    internal class NativeCollider : ScriptObject
+    {
+        private Collider component;
+
+        public Collider Component
+        {
+            get { return component; }
+            set { component = value; }
+        }
+
+        public Vector3 Position
+        {
+            get { Vector3 pos; Internal_GetPosition(mCachedPtr, out pos); return pos; }
+            set { Quaternion rot = Rotation; Internal_SetTransform(mCachedPtr, ref value, ref rot); }
+        }
+
+        public Quaternion Rotation
+        {
+            get { Quaternion rot; Internal_GetRotation(mCachedPtr, out rot); return rot; }
+            set { Vector3 pos = Position; Internal_SetTransform(mCachedPtr, ref pos, ref value); }
+        }
+
+        public Vector3 Scale
+        {
+            get { Vector3 scale; Internal_GetScale(mCachedPtr, out scale); return scale; }
+            set { Internal_SetScale(mCachedPtr, ref value); }
+        }
+
+        public bool IsTrigger
+        {
+            get { return Internal_GetIsTrigger(mCachedPtr); }
+            set { Internal_SetIsTrigger(mCachedPtr, value); }
+        }
+
+        public NativeRigidbody Rigidbody
+        {
+            get { return Internal_GetRigidbody(mCachedPtr); }
+            set
+            {
+                IntPtr rigidbodyPtr = IntPtr.Zero;
+                if (value != null)
+                    rigidbodyPtr = value.GetCachedPtr();
+
+                Internal_SetRigidbody(mCachedPtr, rigidbodyPtr);
+            }
+        }
+
+        public float Mass
+        {
+            get { return Internal_GetMass(mCachedPtr); }
+            set { Internal_SetMass(mCachedPtr, value); }
+        }
+
+        public PhysicsMaterial Material
+        {
+            get { return Internal_GetMaterial(mCachedPtr); }
+            set
+            {
+                IntPtr materialPtr = IntPtr.Zero;
+                if (value != null)
+                    materialPtr = value.GetCachedPtr();
+
+                Internal_SetMaterial(mCachedPtr, materialPtr);
+            }
+        }
+
+        public float ContactOffset
+        {
+            get { return Internal_GetContactOffset(mCachedPtr); }
+            set { Internal_SetContactOffset(mCachedPtr, value); }
+        }
+
+        public float RestOffset
+        {
+            get { return Internal_GetRestOffset(mCachedPtr); }
+            set { Internal_SetRestOffset(mCachedPtr, value); }
+        }
+
+        public ulong Layer
+        {
+            get { return Internal_GetLayer(mCachedPtr); }
+            set { Internal_SetLayer(mCachedPtr, value); }
+        }
+
+        public CollisionReportMode CollisionReportMode
+        {
+            get { return Internal_GetCollisionReportMode(mCachedPtr); }
+            set { Internal_SetCollisionReportMode(mCachedPtr, value); }
+        }
+
+        public bool Raycast(Vector3 origin, Vector3 unitDir, out ScriptPhysicsQueryHit hit, float maxDist)
+        {
+            return Internal_RayCast(mCachedPtr, ref origin, ref unitDir, out hit, maxDist);
+        }
+
+        public void Destroy()
+        {
+            Internal_Destroy(mCachedPtr);
+        }
+
+        private void Internal_DoOnCollisionBegin(ScriptCollisionData scriptCollisionData)
+        {
+            CollisionData collisionData;
+            collisionData.colliderA = scriptCollisionData.colliderA.Component;
+            collisionData.colliderB = scriptCollisionData.colliderB.Component;
+            collisionData.contactPoints = scriptCollisionData.contactPoints;
+
+            Component.DoOnCollisionBegin(collisionData);
+        }
+
+        private void Internal_DoOnCollisionStay(ScriptCollisionData scriptCollisionData)
+        {
+            CollisionData collisionData;
+            collisionData.colliderA = scriptCollisionData.colliderA.Component;
+            collisionData.colliderB = scriptCollisionData.colliderB.Component;
+            collisionData.contactPoints = scriptCollisionData.contactPoints;
+
+            Component.DoOnCollisionStay(collisionData);
+        }
+
+        private void Internal_DoOnCollisionEnd(ScriptCollisionData scriptCollisionData)
+        {
+            CollisionData collisionData;
+            collisionData.colliderA = scriptCollisionData.colliderA.Component;
+            collisionData.colliderB = scriptCollisionData.colliderB.Component;
+            collisionData.contactPoints = scriptCollisionData.contactPoints;
+
+            Component.DoOnCollisionEnd(collisionData);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_Destroy(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetPosition(IntPtr thisPtr, out Vector3 pos);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetRotation(IntPtr thisPtr, out Quaternion rot);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetTransform(IntPtr thisPtr, ref Vector3 pos, ref Quaternion rot);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetScale(IntPtr thisPtr, ref Vector3 scale);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetScale(IntPtr thisPtr, out Vector3 scale);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetIsTrigger(IntPtr thisPtr, bool value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_GetIsTrigger(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetRigidbody(IntPtr thisPtr, IntPtr rigidbody);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern NativeRigidbody Internal_GetRigidbody(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetMass(IntPtr thisPtr, float mass);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern float Internal_GetMass(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetMaterial(IntPtr thisPtr, IntPtr physicsMaterial);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern PhysicsMaterial Internal_GetMaterial(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetContactOffset(IntPtr thisPtr, float value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern float Internal_GetContactOffset(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetRestOffset(IntPtr thisPtr, float value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern float Internal_GetRestOffset(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetLayer(IntPtr thisPtr, ulong layer);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern ulong Internal_GetLayer(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetCollisionReportMode(IntPtr thisPtr, CollisionReportMode mode);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern CollisionReportMode Internal_GetCollisionReportMode(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_RayCast(IntPtr thisPtr, ref Vector3 origin, ref Vector3 unitDir, 
+            out ScriptPhysicsQueryHit hit, float maxDist);
+    }
+}

+ 41 - 0
MBansheeEngine/Physics/NativeMeshCollider.cs

@@ -0,0 +1,41 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Runtime.CompilerServices;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Wrapper around the native MeshCollider class.
+    /// <see cref="MeshCollider"/>
+    /// </summary>
+    internal class NativeMeshCollider : NativeCollider
+    {
+        public NativeMeshCollider()
+        {
+            Internal_CreateInstance(this);
+        }
+
+        public PhysicsMesh Mesh
+        {
+            get { return Internal_GetMesh(mCachedPtr); }
+            set
+            {
+                IntPtr meshPtr = IntPtr.Zero;
+                if (value != null)
+                    meshPtr = value.GetCachedPtr();
+
+                Internal_SetMesh(mCachedPtr, meshPtr);
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateInstance(NativeMeshCollider instance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern PhysicsMesh Internal_GetMesh(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetMesh(IntPtr thisPtr, IntPtr mesh);
+    }
+}

+ 22 - 0
MBansheeEngine/Physics/NativePlaneCollider.cs

@@ -0,0 +1,22 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Runtime.CompilerServices;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Wrapper around the native PlaneCollider class.
+    /// <see cref="PlaneCollider"/>
+    /// </summary>
+    internal class NativePlaneCollider : NativeCollider
+    {
+        public NativePlaneCollider()
+        {
+            Internal_CreateInstance(this);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateInstance(NativePlaneCollider instance);
+    }
+}

+ 7 - 0
MBansheeEngine/Physics/NativeRigidbody.cs

@@ -0,0 +1,7 @@
+namespace BansheeEngine
+{
+    internal class NativeRigidbody : ScriptObject
+    {
+        // TODO
+    }
+}

+ 34 - 0
MBansheeEngine/Physics/NativeSphereCollider.cs

@@ -0,0 +1,34 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Runtime.CompilerServices;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Wrapper around the native SphereCollider class.
+    /// <see cref="SphereCollider"/>
+    /// </summary>
+    internal class NativeSphereCollider : NativeCollider
+    {
+        public NativeSphereCollider()
+        {
+            Internal_CreateInstance(this);
+        }
+
+        public float Radius
+        {
+            get { return Internal_GetRadius(mCachedPtr); }
+            set { Internal_SetRadius(mCachedPtr, value); }
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateInstance(NativeSphereCollider instance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern float Internal_GetRadius(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetRadius(IntPtr thisPtr, float radius);
+    }
+}

+ 135 - 0
MBansheeEngine/Physics/PhysicsCommon.cs

@@ -0,0 +1,135 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System.Runtime.InteropServices;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Hit information from a physics query.
+    /// </summary>
+    public struct PhysicsQueryHit
+    {
+        /// <summary>
+        /// Position of the hit in world space.
+        /// </summary>
+        public Vector3 point;
+
+        /// <summary>
+        /// Normal to the surface that was hit. 
+        /// </summary>
+        public Vector3 normal;
+
+        /// <summary>
+        /// UV coordinates of the triangle that was hit (only applicable when triangle meshes are hit).
+        /// </summary>
+        public Vector2 uv;
+
+        /// <summary>
+        /// Distance from the query origin to the hit position.
+        /// </summary>
+        public float distance;
+
+        /// <summary>
+        /// Index of the triangle that was hit (only applicable when triangle meshes are hit).
+        /// </summary>
+        public int triangleIdx;
+
+        /// <summary>
+        /// Collider that was hit.
+        /// </summary>
+        public Collider collider;
+    }
+
+    /// <summary>
+    /// Information about a single contact point during physics collision.
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct ContactPoint // Note: Must match C++ ContactPoint struct
+    {
+        /// <summary>
+        /// Contact point in world space.
+        /// </summary>
+        public Vector3 position;
+
+        /// <summary>
+        /// Normal pointing from the second shape to the first shape.
+        /// </summary>
+        public Vector3 normal;
+
+        /// <summary>
+        /// Impulse applied to the objects to keep them from penetrating. Divide by simulation step to get the force.
+        /// </summary>
+        public float impulse;
+
+        /// <summary>
+        /// Determines how far are the objects. Negative value denotes penetration.
+        /// </summary>
+        public float separation;
+    };
+
+    /// <summary>
+    /// Information about a collision between two physics objects.
+    /// </summary>
+    public struct CollisionData
+    {
+        /// <summary>
+        /// First of the colliders involved in the collision.
+        /// </summary>
+        public Collider colliderA;
+
+        /// <summary>
+        /// Second of the colliders involved in the collision.
+        /// </summary>
+        public Collider colliderB;
+
+        /// <summary>
+        /// Information about all the contact points for the hit. 
+        /// </summary>
+        public ContactPoint[] contactPoints;
+    };
+
+    /// <summary>
+    /// Interop class used for passing PhysicsQueryHit data from native to managed code. <see cref="PhysicsQueryHit"/>.
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct ScriptPhysicsQueryHit // Note: Must match C++ struct ScriptPhysicsQueryHit
+    {
+        public Vector3 point;
+        public Vector3 normal;
+        public Vector2 uv;
+        public float distance;
+        public int triangleIdx;
+        public NativeCollider collider;
+    }
+
+    /// <summary>
+    /// Interop class used for passing CollisionData data from native to managed code. <see cref="CollisionData"/>.
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct ScriptCollisionData // Note: Must match C++ CollisionData struct
+    {
+        public NativeCollider colliderA;
+        public NativeCollider colliderB;
+        public ContactPoint[] contactPoints;
+    };
+
+    /// <summary>
+    /// Determines which collision events will be reported by physics objects.
+    /// </summary>
+    public enum CollisionReportMode
+    {
+        /// <summary>
+        /// No collision events will be triggered.
+        /// </summary>
+        None,
+        /// <summary>
+        /// Collision events will be triggered when object enters and/or leaves collision.
+        /// </summary>
+		Report,
+		/// <summary>
+        /// Collision events will be triggered when object enters and/or leaves collision, but also every frame the object 
+        /// remains in collision. 
+        /// </summary>
+		ReportPersistent, 
+	};
+}

+ 0 - 0
MBansheeEngine/PhysicsMaterial.cs → MBansheeEngine/Physics/PhysicsMaterial.cs


+ 0 - 0
MBansheeEngine/PhysicsMesh.cs → MBansheeEngine/Physics/PhysicsMesh.cs


+ 73 - 0
MBansheeEngine/Physics/PlaneCollider.cs

@@ -0,0 +1,73 @@
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Collider with plane geometry.
+    /// </summary>
+    public sealed class PlaneCollider : Collider
+    {
+        [SerializeField]
+        private float distance;
+
+        [SerializeField]
+        private Vector3 normal;
+
+        /// <summary>
+        /// Distance of the plane from the local origin, along its normal vector.
+        /// </summary>
+        public float Distance
+        {
+            get { return distance; }
+            set
+            {
+                if (distance == value)
+                    return;
+
+                distance = value;
+                serializableData.localPosition = normal * distance;
+
+                if (Native != null)
+                    UpdateTransform();
+            }
+        }
+
+        /// <summary>
+        /// Normal vector of the plane. It determines how is the plane oriented.
+        /// </summary>
+        public Vector3 Normal
+        {
+            get { return normal; }
+            set
+            {
+                if (normal == value)
+                    return;
+
+                normal = value.Normalized;
+                serializableData.localRotation = Quaternion.FromToRotation(Vector3.XAxis, normal);
+
+                if (Native != null)
+                    UpdateTransform();
+            }
+        }
+
+        /// <inheritdoc/>
+        protected override bool IsValidParent(Rigidbody parent)
+    	{
+		    // Planes cannot be added to non-kinematic rigidbodies
+		    return parent.IsKinematic;
+        }
+
+        /// <summary>
+        /// Returns the native plane collider wrapped by this component.
+        /// </summary>
+        private NativePlaneCollider Native
+        {
+            get { return (NativePlaneCollider)native; }
+        }
+
+        /// <inheritdoc/>
+        internal override NativeCollider CreateCollider()
+        {
+            return new NativePlaneCollider();
+        }
+    }
+}

+ 7 - 0
MBansheeEngine/Physics/Rigidbody.cs

@@ -0,0 +1,7 @@
+namespace BansheeEngine
+{
+    public class Rigidbody : Component
+    {
+        // TODO
+    }
+}

+ 69 - 0
MBansheeEngine/Physics/SphereCollider.cs

@@ -0,0 +1,69 @@
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Collider with sphere geometry.
+    /// </summary>
+    public sealed class SphereCollider : Collider
+    {
+        [SerializeField]
+        private float radius;
+
+        /// <summary>
+        /// Radius of the sphere.
+        /// </summary>
+        public float Radius
+        {
+            get { return radius; }
+            set
+            {
+                if (radius == value)
+                    return;
+
+                radius = value;
+
+                if (Native != null)
+                {
+                    Native.Radius = value;
+
+                    if (parent != null)
+                        parent.UpdateMassDistribution();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Position of the sphere shape, relative to the component's scene object.
+        /// </summary>
+        public Vector3 Center
+        {
+            get { return serializableData.localPosition; }
+            set
+            {
+                if (serializableData.localPosition == value)
+                    return;
+
+                serializableData.localPosition = value;
+
+                if (Native != null)
+                    UpdateTransform();
+            }
+        }
+
+        /// <summary>
+        /// Returns the native sphere collider wrapped by this component.
+        /// </summary>
+        private NativeSphereCollider Native
+        {
+            get { return (NativeSphereCollider)native; }
+        }
+
+        /// <inheritdoc/>
+        internal override NativeCollider CreateCollider()
+        {
+            NativeSphereCollider sphereCollider = new NativeSphereCollider();
+            sphereCollider.Radius = radius;
+
+            return sphereCollider;
+        }
+    }
+}

+ 9 - 0
SBansheeEngine/Include/BsScriptCollider.h

@@ -8,6 +8,8 @@
 
 namespace BansheeEngine
 {
+	class ScriptCollider;
+
 	/** Base class for all Collider interop objects. */
 	class BS_SCR_BE_EXPORT ScriptColliderBase : public ScriptObjectBase
 	{
@@ -15,12 +17,17 @@ namespace BansheeEngine
 		/** Returns the native Collider object. */
 		virtual Collider* getCollider() const { return mCollider.get(); };
 	protected:
+		friend ScriptCollider;
+
 		ScriptColliderBase(MonoObject* instance);
 		virtual ~ScriptColliderBase() {}
 
 		/** Initializes the interop object with a native collider. Must be called right after construction. */
 		void initialize(const SPtr<Collider>& collider);
 
+		/** Destroys the internal collider object. */
+		void destroyCollider();
+
 		SPtr<Collider> mCollider;
 	};
 
@@ -60,6 +67,8 @@ namespace BansheeEngine
 		/************************************************************************/
 		/* 								CLR HOOKS						   		*/
 		/************************************************************************/
+		static void internal_Destroy(ScriptColliderBase* thisPtr);
+		
 		static void internal_GetPosition(ScriptColliderBase* thisPtr, Vector3* pos);
 		static void internal_GetRotation(ScriptColliderBase* thisPtr, Quaternion* rot);
 		static void internal_SetTransform(ScriptColliderBase* thisPtr, Vector3* pos, Quaternion* rot);

+ 2 - 2
SBansheeEngine/Include/BsScriptCollisionData.h

@@ -9,7 +9,7 @@
 namespace BansheeEngine
 {
 	/** Interop struct between C++ & CLR for CollisionData. */
-	struct ScriptCollisionData // Must match C# CollisionData struct layout
+	struct ScriptCollisionData // Must match C# ScriptCollisionData struct layout
 	{
 		MonoObject* colliderA;
 		MonoObject* colliderB;
@@ -19,7 +19,7 @@ namespace BansheeEngine
 	/** Helper class for dealing with CollisionData structure. */
 	class BS_SCR_BE_EXPORT ScriptCollisionDataHelper : public ScriptObject<ScriptCollisionDataHelper>
 	{
-		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "CollisionData")
+		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "ScriptCollisionData")
 
 	public:
 		/** Converts native collision data to its managed counterpart. */

+ 2 - 2
SBansheeEngine/Include/BsScriptPhysicsQueryHit.h

@@ -9,7 +9,7 @@
 namespace BansheeEngine
 {
 	/** Interop struct between C++ & CLR for PhysicsQueryHit. */
-	struct ScriptPhysicsQueryHit // Must match C# PhysicsQueryHit struct layout
+	struct ScriptPhysicsQueryHit // Must match C# ScriptPhysicsQueryHit struct layout
 	{
 		Vector3 point;
 		Vector3 normal;
@@ -22,7 +22,7 @@ namespace BansheeEngine
 	/** Helper class for dealing with PhysicsQueryHit structure. */
 	class BS_SCR_BE_EXPORT ScriptPhysicsQueryHitHelper : public ScriptObject<ScriptPhysicsQueryHitHelper>
 	{
-		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "PhysicsQueryHit")
+		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "ScriptPhysicsQueryHit")
 
 	public:
 		/** Converts native physics query hit to its managed counterpart. */

+ 11 - 0
SBansheeEngine/Source/BsScriptCollider.cpp

@@ -34,12 +34,18 @@ namespace BansheeEngine
 		collider->onCollisionEnd.connect(std::bind(&Collider::onCollisionEnd, instance, _1));
 	}
 
+	void ScriptColliderBase::destroyCollider()
+	{
+		mCollider = nullptr;
+	}
+
 	ScriptCollider::ScriptCollider(MonoObject* instance)
 		:TScriptCollider(instance, nullptr)
 	{ }
 
 	void ScriptCollider::initRuntimeData()
 	{
+		metaData.scriptClass->addInternalCall("Internal_Destroy", &ScriptCollider::internal_Destroy);
 		metaData.scriptClass->addInternalCall("Internal_GetPosition", &ScriptCollider::internal_GetPosition);
 		metaData.scriptClass->addInternalCall("Internal_GetRotation", &ScriptCollider::internal_GetRotation);
 		metaData.scriptClass->addInternalCall("Internal_SetTransform", &ScriptCollider::internal_SetTransform);
@@ -86,6 +92,11 @@ namespace BansheeEngine
 		MonoUtil::invokeThunk(onCollisionEndThunk, instance, managedCollisionData);
 	}
 
+	void ScriptCollider::internal_Destroy(ScriptColliderBase* thisPtr)
+	{
+		thisPtr->destroyCollider();
+	}
+
 	void ScriptCollider::internal_GetPosition(ScriptColliderBase* thisPtr, Vector3* pos)
 	{
 		*pos = thisPtr->getCollider()->getPosition();