/// <summary> /// setup projectile for fireing /// </summary> public virtual void setup() { OnHit = () => { if (hitInfo.hitObject) { RagdollManager ragMan = null; ragMan = hitInfo.hitObject.GetComponent <RagdollManager>(); if (!ragMan) { #if DEBUG_INFO Debug.LogError("Ball::OnHit cannot find RagdollManager component on " + hitInfo.hitObject.name + "."); #endif return; } if (!ragMan.acceptHit) { return; } Vector3 force = hitInfo.hitDirection * CurrentHitStrength; ragMan.startHitReaction(hitInfo.bodyPartIndices, force); } }; }
/// <summary> /// update projectile /// </summary> protected virtual void updateSpheremarch() { Vector3 transformPosition = transform.position; // advance lifetime starting from time when fired onwards if (m_State != ProjectileStates.Ready) { m_CurrentLifetime += Time.deltaTime; if (m_CurrentLifetime > lifetime) { if (m_OnLifetimeExpire != null) { m_OnLifetimeExpire(this); } else { Destroy(this.gameObject); } return; } } #if DEBUG_DRAW positionList.Add(transformPosition); radiusList.Add(m_SphereCollider.radius * this.transform.localScale.x); #endif // check for collision only when fired if (m_State == ProjectileStates.Fired && m_LastPosition.HasValue) { // shoot sphere from last position to current // and check if we have a hit int mask = collidingLayers; #if DEBUG_INFO if (!m_SphereCollider) { Debug.LogError("SphereCollider missing." + " < " + this.ToString() + ">"); return; } #endif float radius = m_SphereCollider.radius * this.transform.localScale.x; Vector3 difference = transformPosition - m_LastPosition.Value; Vector3 direction = difference.normalized; float length = difference.magnitude; Vector3 rayPos = m_LastPosition.Value; Ray ray = new Ray(rayPos, direction); RaycastHit[] hits = Physics.SphereCastAll(ray, radius, length, mask); List <int> chosenHits = new List <int>(); RagdollManager ragMan = null; RaycastHit?rayhit = null; for (int i = 0; i < hits.Length; i++) { RaycastHit rhit = hits[i]; BodyColliderScript bcs = rhit.collider.GetComponent <BodyColliderScript>(); if (!bcs) { #if DEBUG_INFO Debug.LogError("BodyColliderScript missing on " + rhit.collider.name); #endif continue; } if (!bcs.ParentObject) { #if DEBUG_INFO Debug.LogError("BodyColliderScript.ParentObject missing on " + rhit.collider.name); #endif continue; } if (bcs.ParentObject == this.m_Owner) { continue; } if (!ragMan) { ragMan = bcs.ParentRagdollManager; m_HitInfo.hitObject = bcs.ParentObject; m_HitInfo.collider = rhit.collider; m_HitInfo.hitDirection = direction; m_HitInfo.hitStrength = m_CurrentHitStrength; rayhit = rhit; } chosenHits.Add(bcs.index); } if (hits.Length > 0) { if (ragMan) { if (!rayhit.HasValue) { #if DEBUG_INFO Debug.LogError("object cannot be null." + " < " + this.ToString() + ">"); #endif return; } Vector3 n = rayhit.Value.normal; Vector3 r = Vector3.Reflect(direction, n); this.transform.position = rayPos + ray.direction * (rayhit.Value.distance - radius); Vector3 vel = r; this.m_Rigidbody.velocity = vel; m_HitInfo.bodyPartIndices = chosenHits.ToArray(); m_State = ProjectileStates.Done; m_CurrentHitStrength = vel.magnitude; m_CurrentHitStrength += m_HitStrength; if (m_OnHit != null) { m_OnHit(); } else { Vector3 force = direction * m_CurrentHitStrength; ragMan.startHitReaction(m_HitInfo.bodyPartIndices, force); } if (m_OnAfterHit != null) { m_OnAfterHit(); } } #if DEBUG_INFO else { BodyColliderScript bcs = hits[0].collider.GetComponent <BodyColliderScript>(); if (!bcs) { return; } if (!bcs.ParentObject) { return; } if (bcs.ParentObject == this.m_Owner) { return; } Debug.LogWarning("RagdollUser interface not implemented. " + bcs.ParentObject.name); } #endif } } m_LastPosition = transformPosition; }