// (c) Copyright HutongGames, LLC 2010-2016. All rights reserved. using UnityEngine; namespace HutongGames.PlayMaker.Actions { [ActionCategory(ActionCategory.Physics2D)] [Tooltip("Detect collisions between Game Objects that have RigidBody2D/Collider2D components.")] public class Collision2dEvent : FsmStateAction { [Tooltip("The GameObject to detect collisions on.")] public FsmOwnerDefault gameObject; [Tooltip("The type of collision to detect.")] public Collision2DType collision; [UIHint(UIHint.TagMenu)] [Tooltip("Filter by Tag.")] public FsmString collideTag; [Tooltip("Event to send if a collision is detected.")] public FsmEvent sendEvent; [UIHint(UIHint.Variable)] [Tooltip("Store the GameObject that collided with the Owner of this FSM.")] public FsmGameObject storeCollider; [UIHint(UIHint.Variable)] [Tooltip("Store the force of the collision. NOTE: Use Get Collision 2D Info to get more info about the collision.")] public FsmFloat storeForce; // cached proxy component for callbacks private PlayMakerProxyBase cachedProxy; public override void Reset() { collision = Collision2DType.OnCollisionEnter2D; collideTag = ""; sendEvent = null; storeCollider = null; storeForce = null; } public override void OnPreprocess() { if (gameObject == null) gameObject = new FsmOwnerDefault(); if (gameObject.OwnerOption == OwnerDefaultOption.UseOwner) { switch (collision) { case Collision2DType.OnCollisionEnter2D: Fsm.HandleCollisionEnter2D = true; break; case Collision2DType.OnCollisionStay2D: Fsm.HandleCollisionStay2D = true; break; case Collision2DType.OnCollisionExit2D: Fsm.HandleCollisionExit2D = true; break; case Collision2DType.OnParticleCollision: Fsm.HandleParticleCollision = true; break; } } else { // Add proxy components now if we can GetProxyComponent(); } } public override void OnEnter() { if (gameObject.OwnerOption == OwnerDefaultOption.UseOwner) return; if (cachedProxy == null) GetProxyComponent(); AddCallback(); gameObject.GameObject.OnChange += UpdateCallback; } public override void OnExit() { if (gameObject.OwnerOption == OwnerDefaultOption.UseOwner) return; RemoveCallback(); gameObject.GameObject.OnChange -= UpdateCallback; } private void UpdateCallback() { RemoveCallback(); GetProxyComponent(); AddCallback(); } private void GetProxyComponent() { cachedProxy = null; var source = gameObject.GameObject.Value; if (source == null) return; switch (collision) { case Collision2DType.OnCollisionEnter2D: cachedProxy = PlayMakerFSM.GetEventHandlerComponent(source); break; case Collision2DType.OnCollisionStay2D: cachedProxy = PlayMakerFSM.GetEventHandlerComponent(source); break; case Collision2DType.OnCollisionExit2D: cachedProxy = PlayMakerFSM.GetEventHandlerComponent(source); break; case Collision2DType.OnParticleCollision: cachedProxy = PlayMakerFSM.GetEventHandlerComponent(source); break; } } private void AddCallback() { if (cachedProxy == null) return; switch (collision) { case Collision2DType.OnCollisionEnter2D: cachedProxy.AddCollision2DEventCallback(CollisionEnter2D); break; case Collision2DType.OnCollisionStay2D: cachedProxy.AddCollision2DEventCallback(CollisionStay2D); break; case Collision2DType.OnCollisionExit2D: cachedProxy.AddCollision2DEventCallback(CollisionExit2D); break; case Collision2DType.OnParticleCollision: cachedProxy.AddParticleCollisionEventCallback(ParticleCollision); break; } } private void RemoveCallback() { if (cachedProxy == null) return; switch (collision) { case Collision2DType.OnCollisionEnter2D: cachedProxy.RemoveCollision2DEventCallback(CollisionEnter2D); break; case Collision2DType.OnCollisionStay2D: cachedProxy.RemoveCollision2DEventCallback(CollisionStay2D); break; case Collision2DType.OnCollisionExit2D: cachedProxy.RemoveCollision2DEventCallback(CollisionExit2D); break; case Collision2DType.OnParticleCollision: cachedProxy.RemoveParticleCollisionEventCallback(ParticleCollision); break; } } private void StoreCollisionInfo(Collision2D collisionInfo) { storeCollider.Value = collisionInfo.gameObject; storeForce.Value = collisionInfo.relativeVelocity.magnitude; } public override void DoCollisionEnter2D(Collision2D collisionInfo) { if (gameObject.OwnerOption == OwnerDefaultOption.UseOwner) CollisionEnter2D(collisionInfo); } public override void DoCollisionStay2D(Collision2D collisionInfo) { if (gameObject.OwnerOption == OwnerDefaultOption.UseOwner) CollisionStay2D(collisionInfo); } public override void DoCollisionExit2D(Collision2D collisionInfo) { if (gameObject.OwnerOption == OwnerDefaultOption.UseOwner) CollisionExit2D(collisionInfo); } public override void DoParticleCollision(GameObject other) { if (gameObject.OwnerOption == OwnerDefaultOption.UseOwner) ParticleCollision(other); } private void CollisionEnter2D(Collision2D collisionInfo) { if (collision == Collision2DType.OnCollisionEnter2D) { if (TagMatches(collideTag, collisionInfo)) { StoreCollisionInfo(collisionInfo); Fsm.Event(sendEvent); } } } private void CollisionStay2D(Collision2D collisionInfo) { if (collision == Collision2DType.OnCollisionStay2D) { if (TagMatches(collideTag, collisionInfo)) { StoreCollisionInfo(collisionInfo); Fsm.Event(sendEvent); } } } private void CollisionExit2D(Collision2D collisionInfo) { if (collision == Collision2DType.OnCollisionExit2D) { if (TagMatches(collideTag, collisionInfo)) { StoreCollisionInfo(collisionInfo); Fsm.Event(sendEvent); } } } private void ParticleCollision(GameObject other) { if (collision == Collision2DType.OnParticleCollision) { if (TagMatches(collideTag, other)) { if (storeCollider != null) storeCollider.Value = other; storeForce.Value = 0f; //TODO: impact force? Fsm.Event(sendEvent); } } } public override string ErrorCheck() { return ActionHelpers.CheckPhysics2dSetup(Fsm.GetOwnerDefaultTarget(gameObject)); } } }