wangguan
2020-10-27 06430ef49a970c718e10c1ef8154d969e9906401
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
using ActionGameFramework.Health;
using ActionGameFramework.Helpers;
using Core.Health;
using UnityEngine;
 
namespace ActionGameFramework.Projectiles
{
    /// <summary>
    /// Basic override of LinearProjectile that allows them to adjust their path in-flight to intercept a designated target.
    /// </summary>
    public class HomingLinearProjectile : LinearProjectile
    {
        public int leadingPrecision = 2;
 
        public bool leadTarget;
 
        protected Targetable m_HomingTarget;
 
        Vector3 m_TargetVelocity;
 
        /// <summary>
        /// Sets the target transform that will be homed in on once fired.
        /// </summary>
        /// <param name="target">Transform of the target to home in on.</param>
        public void SetHomingTarget(Targetable target)
        {
            m_HomingTarget = target;
        }
 
        protected virtual void FixedUpdate()
        {
            if (m_HomingTarget == null)
            {
                return;
            }
 
            m_TargetVelocity = m_HomingTarget.velocity;
        }
 
        protected override void Update()
        {
            if (!m_Fired)
            {
                return;
            }
 
            if (m_HomingTarget == null)
            {
                m_Rigidbody.rotation = Quaternion.LookRotation(m_Rigidbody.velocity);
                return;
            }
 
            Quaternion aimDirection = Quaternion.LookRotation(GetHeading());
 
            m_Rigidbody.rotation = aimDirection;
            m_Rigidbody.velocity = transform.forward * m_Rigidbody.velocity.magnitude;
 
            base.Update();
        }
 
        protected Vector3 GetHeading()
        {
            if (m_HomingTarget == null)
            {
                return Vector3.zero;
            }
            Vector3 heading;
            if (leadTarget)
            {
                heading = Ballistics.CalculateLinearLeadingTargetPoint(transform.position, m_HomingTarget.position,
                                                                       m_TargetVelocity, m_Rigidbody.velocity.magnitude,
                                                                       acceleration,
                                                                       leadingPrecision) - transform.position;
            }
            else
            {
                heading = m_HomingTarget.position - transform.position;
            }
 
            return heading.normalized;
        }
 
        protected override void Fire(Vector3 firingVector)
        {
            if (m_HomingTarget == null)
            {
                Debug.LogError("Homing target has not been specified. Aborting fire.");
                return;
            }
            m_HomingTarget.removed += OnTargetDied;
 
            base.Fire(firingVector);
        }
 
        void OnTargetDied(DamageableBehaviour targetable)
        {
            targetable.removed -= OnTargetDied;
            m_HomingTarget = null;
        }
    }
}