/// --------------------------------------------- /// Ultimate Character Controller /// Copyright (c) Opsive. All Rights Reserved. /// https://www.opsive.com /// --------------------------------------------- namespace Opsive.UltimateCharacterController.Objects.ItemAssist { using Opsive.Shared.Game; using UnityEngine; /// /// Represents a shell casing which uses the trajectory object for kinematic shell movement. /// [RequireComponent(typeof(Rigidbody))] public class Shell : TrajectoryObject { [Tooltip("Time to live in seconds before the shell is removed.")] [SerializeField] protected float m_Lifespan = 10; [Tooltip("Chance of shell not being removed after settling on the ground.")] [Range(0, 1)] [SerializeField] protected float m_Persistence = 1; private float m_RemoveTime; private Vector3 m_StartScale; /// /// Initialize the default values. /// protected override void Awake() { base.Awake(); m_StartScale = transform.localScale; // The Rigidbody is only used to notify Unity that the object isn't static. The Rigidbody doesn't control any movement. var rigidbody = GetComponent(); rigidbody.mass = m_Mass; rigidbody.isKinematic = true; rigidbody.constraints = RigidbodyConstraints.FreezeAll; } /// /// The shell has been spawned - reset the timing and component values. /// protected override void OnEnable() { base.OnEnable(); m_RemoveTime = Time.time + m_Lifespan; m_Transform.localScale = m_StartScale; if (m_Collider != null) { m_Collider.enabled = true; } } /// /// Move and rotate the object according to a parabolic trajectory. /// protected override void FixedUpdate() { base.FixedUpdate(); if (Time.time > m_RemoveTime) { // The shell should be removed. m_Transform.localScale = Vector3.Lerp(m_Transform.localScale, Vector3.zero, Utility.TimeUtility.FramerateDeltaTime * 0.2f); if (Time.time > m_RemoveTime + 0.5f) { ObjectPool.Destroy(m_GameObject); } } } /// /// The object has collided with another object. /// /// The RaycastHit of the object. Can be null. protected override void OnCollision(RaycastHit? hit) { base.OnCollision(hit); if (m_Velocity.sqrMagnitude > 4) { // Hard bounce. // Apply more random rotation velocity to make the shell behave a bit unpredictably on a hard bounce (similar to real brass shell behavior). AddTorque(Random.rotation.eulerAngles * 0.15f * (Random.value > 0.5f ? 1 : -1)); } else if (Random.value > m_Persistence) { // Soft bounce. // Remove the shell after half a second on a soft bounce. m_RemoveTime = Time.time + 0.5f; } } } }