playMaker

Author Topic: KnockbackGameObject  (Read 2435 times)

ransomink

  • Playmaker Newbie
  • *
  • Posts: 44
KnockbackGameObject
« on: January 03, 2018, 05:51:49 PM »
A neat action that knocks a game object back based on its hit direction. This one is not physics-based. I'll probably make that one later...

Code: [Select]
// (c) Copyright HutongGames, LLC 2010-2018. All rights reserved.
// author : ransomink
// Keywords: back, gameobject, knock, knockback
/*--- __ECO__ __PLAYMAKER__ __ACTION__ ---*/

using UnityEngine;

namespace HutongGames.PlayMaker.Actions
{

    [ActionCategory(ActionCategory.GameObject)]
    [Tooltip("Knock back a GameObject based on its hit direction.")]
    public class KnockbackGameObject : FsmStateAction
    {
        [RequiredField]
        [UIHint(UIHint.Variable)]
        [Tooltip("GameObject to knockback.")]
        public FsmOwnerDefault gameObject;

        [RequiredField]
        [Tooltip("Target GameObject.")]
        public FsmGameObject target;

        [RequiredField]
        [Tooltip("Amount of force applied to the game object.")]
        public FsmFloat force;

        [RequiredField]
        [Tooltip("Vertical force applied to the game object.")]
        public FsmFloat height;

        [RequiredField]
        [Tooltip("Length in seconds of knockback.")]
        public FsmFloat duration;

        [Tooltip("Knockback animation curve")]
        public FsmAnimationCurve animationCurve;

        [Tooltip("Use unscaled time. Not affected by Time.timeScale (slow motion effects).")]
        public bool realTime;

        /// <summary>
        /// The gameObject Transform.
        /// </summary>
        private Transform _t;

        /// <summary>
        /// Knockback position.
        /// </summary>
        private Vector3 _knockbackPos;

        /// <summary>
        /// Local position of the gameObject.
        /// </summary>
        private Vector3 _localPos;

        /// <summary>
        /// Direction to move towards.
        /// </summary>
        private Vector3 _direction;

        /// <summary>
        /// Beginning of knockback.
        /// </summary>
        private float _startTime;

        /// <summary>
        /// End of knockback.
        /// </summary>
        private float _endTime;

        /// <summary>
        /// Knockback the gameobject?
        /// </summary>
        private bool _knockback;

        /// <summary>
        /// Get the current time.
        /// </summary>
        private float CurrentTime
        {
            get { return realTime ? Time.unscaledTime : Time.time; }
        }

        public override void Reset()
        {
            gameObject     = null;
            target         = null;
            force          = null;
            height         = null;
            duration       = 0.5f;
            animationCurve = null;
            realTime       = false;
        }

        public override void OnEnter()
    {
            DoKnockback();
    }

        public override void OnUpdate()
        {
            if ( _knockback )
            {
                if ( CurrentTime >= _endTime )
                {
                    _knockback = false;
                    Finish();
                }
                else
                {
                    Move();
                }
            }
        }

        void DoKnockback()
        {
            var go = Fsm.GetOwnerDefaultTarget( gameObject );

            if ( go == null || target == null )
            {
                return;
            }

            _t         = go.transform;
            _localPos  = Vector3.zero;
            _direction = Vector3.zero;
            _startTime = CurrentTime;
            _endTime   = _startTime + duration.Value;

            var a      = _t.position;
            var b      = target.Value.transform.position;
           
            _direction.Set( ( b.x - a.x ), ( b.y - a.y ), ( b.z - a.z ) );
            _direction    = _direction.normalized;
            _localPos     = _t.localPosition;
            _direction.y  = -height.Value;
            _knockbackPos = _t.position - ( _direction * force.Value );
            _knockback    = true;
        }

        void Move()
        {
            _t.localPosition = Vector3.Lerp( _localPos, _knockbackPos, animationCurve.curve.Evaluate( Mathf.InverseLerp( _startTime, _endTime, CurrentTime ) ) );
        }
    }

}
« Last Edit: January 06, 2018, 05:22:09 AM by ransomink »

Fat Pug Studio

  • Beta Group
  • Hero Member
  • *
  • Posts: 1294
    • Fat Pug Studio
Re: KnockbackGameObject
« Reply #1 on: January 05, 2018, 05:21:01 AM »
Great stuff, i was actually looking for something like this, thanks!
Available for Playmaker work

ransomink

  • Playmaker Newbie
  • *
  • Posts: 44
Re: KnockbackGameObject
« Reply #2 on: January 06, 2018, 05:50:51 AM »
I updated the action and added a realtime option in case of any slow or time-controlled effect...