EVP (Edy's Vehicle Physics) Integration Enhancement

macusernick

New member
@Justin Hopefully it's okay to post this Code for the EVP integration. I know that you need special access to download the original integration. If you want me to take this down, please just let me know!

Okay... so here is the (very) small list of changes/enhancements I've made:
  • Added auto-braking when exiting the vehicle (you can adjust the brake/handbrake amounts)
  • Fixed Nitro control (it was not there before)
  • EVP Camera is now referenced directly (in case you want multiple cameras)
  • OnImpact UnityEvent hook is available (it is limited though)
I've started working on the following:
  • Ejecting from the car (I'm not sure how this should be tackled though)

Enjoy!

C#:
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------

namespace Opsive.UltimateCharacterController.Integrations.EdysVehiclePhysics
{
    using EVP;
    using Opsive.Shared.Game;
    using Opsive.Shared.Events;
    using Opsive.UltimateCharacterController.Camera;
    using Opsive.UltimateCharacterController.Character;
    using Opsive.UltimateCharacterController.Objects.CharacterAssist;
    using UnityEngine;
    using UnityEngine.Events;

    [System.Serializable] public class ImpactEvent : UnityEvent<float, Vector3, Vector3, GameObject> {}

    /// <summary>
    /// Implements IDriveSource for an EVP vehicle.
    /// </summary>
    public class EVPDriveSource : MonoBehaviour, IDriveSource
    {
        [Tooltip("The location that the character drives from.")]
        [SerializeField] protected Transform m_DriverLocation;

        [Tooltip("The animator id for custom animations.")]
        [SerializeField] protected int m_AnimatorID;

        [Tooltip("The amount of brake to apply when vehicle is disabled")]
        [SerializeField] protected float m_ForceBrakeAmount = 1f;

        [Tooltip("The amount of handbrake to apply when vehicle is disabled")]
        [SerializeField] protected float m_ForceHandbrakeAmount = 1f;

        //[Tooltip("The speed at which you eject from the vehicle")]
        //[SerializeField] protected float m_EjectSpeed = 20f;

        [Tooltip("Edys Vehicle Camera Controller reference. Leave blank to use UCC camera instead.")]
        [SerializeField] protected VehicleCameraController m_VehicleCameraController;

        public ImpactEvent m_ImpactEvent;


        private GameObject m_GameObject;
        private Transform m_Transform;
        private Collider[] m_IgnoreColliders;

        private VehicleStandardInput m_VehicleStandardInput;
        private VehicleController m_VehicleController;
        private VehicleDamage m_VehicleDamage;
        private VehicleNitro m_VehicleNitro;
        private GameObject m_Character;

        public GameObject GameObject { get => m_GameObject; }
        public Transform Transform { get => m_Transform; }
        public Transform DriverLocation { get => m_DriverLocation; }
        public int AnimatorID { get => m_AnimatorID; }

        /// <summary>
        /// Initialize the default values.
        /// </summary>
        private void Start()
        {
            m_GameObject = gameObject;
            m_Transform = transform;
            m_IgnoreColliders = m_GameObject.GetComponentsInChildren<Collider>();

            m_VehicleStandardInput = m_GameObject.GetComponent<VehicleStandardInput>();
            if (m_VehicleStandardInput == null) {
                Debug.LogError("Error: The EVPDriveSource must be attached to a vehicle with the Edy Vehicle Controller attached to it.");
                return;
            }

            m_VehicleController = m_GameObject.GetComponent<VehicleController>();
            m_VehicleDamage = m_GameObject.GetComponent<VehicleDamage>();
            m_VehicleNitro = m_GameObject.GetComponent<VehicleNitro>();

            EnableDisableVehicle(false);
        }

        /// <summary>
        /// Enables or disables the EVP components.
        /// </summary>
        /// <param name="enable">Should the vehicle be enabled?</param>
        private void EnableDisableVehicle(bool enable)
        {
            if (m_VehicleStandardInput == null) {
                return;
            }

            m_VehicleStandardInput.enabled = enable;

            if(m_VehicleNitro != null) {
                m_VehicleNitro.enabled = enable;
            }

            m_VehicleController.throttleInput = 0f;
            m_VehicleController.brakeInput = m_ForceBrakeAmount;
            m_VehicleController.handbrakeInput = m_ForceHandbrakeAmount;

            if (m_VehicleCameraController != null) {
                m_VehicleCameraController.enabled = enable;
                if (m_Character != null) {
                    // Edy's Vehicle Camera Controller can take control of the camera.
                    var cameraController = m_Character.GetCachedComponent<UltimateCharacterLocomotion>().LookSource as CameraController;
                    if (cameraController != null) {
                        cameraController.enabled = !enable;
                        cameraController.transform.parent = enable ? m_VehicleCameraController.transform : null;
                        // Edy's Vehicle Camera Controller requires the camera to be parented to itself.
                        if (enable) {
                            cameraController.transform.localPosition = Vector3.zero;
                            cameraController.transform.localRotation = Quaternion.identity;
                        }
                        // The handler should be enabled or disabled in addition to the Camera Controller.
                        var cameraControllerHandler = cameraController.gameObject.GetCachedComponent<CameraControllerHandler>();
                        if (cameraControllerHandler != null) {
                            cameraControllerHandler.enabled = !enable;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// The character has started to enter the vehicle.
        /// </summary>
        /// <param name="character">The character that is entering the vehicle.</param>
        public void EnterVehicle(GameObject character)
        {
            var characterLocomotion = character.GetCachedComponent<UltimateCharacterLocomotion>();
            for (int i = 0; i < m_IgnoreColliders.Length; ++i) {
                for (int j = 0; j < characterLocomotion.ColliderCount; ++j) {
                    Physics.IgnoreCollision(m_IgnoreColliders[i], characterLocomotion.Colliders[j], true);
                }
            }
            characterLocomotion.AddIgnoredColliders(m_IgnoreColliders);
        }

        /// <summary>
        /// The character has entered the vehicle.
        /// </summary>
        /// <param name="character">The character that entered the vehicle.</param>
        public void EnteredVehicle(GameObject character)
        {
            m_Character = character;
            EnableDisableVehicle(true);
        }

        /// <summary>
        /// The character has started to exit the vehicle.
        /// </summary>
        /// <param name="character">The character that is exiting the vehicle.</param>
        public void ExitVehicle(GameObject character)
        {
            EnableDisableVehicle(false);
            m_Character = null;
        }

        /// <summary>
        /// The character has exited the vehicle.
        /// </summary>
        /// <param name="character">The character that exited the vehicle.</param>
        public void ExitedVehicle(GameObject character)
        {
            var characterLocomotion = character.GetCachedComponent<UltimateCharacterLocomotion>();
            characterLocomotion.RemoveIgnoredColliders(m_IgnoreColliders);
            for (int i = 0; i < m_IgnoreColliders.Length; ++i) {
                for (int j = 0; j < characterLocomotion.ColliderCount; ++j) {
                    Physics.IgnoreCollision(m_IgnoreColliders[i], characterLocomotion.Colliders[j], false);
                }
            }
        }

        public void Awake()
        {
            EventHandler.RegisterEvent<float, Vector3, Vector3, GameObject, object, Collider>(gameObject, "OnObjectImpact", OnImpact);
        }

        /// <summary>
        /// The object has been impacted with another object.
        /// </summary>
        /// <param name="amount">The amount of damage taken.</param>
        /// <param name="position">The position of the damage.</param>
        /// <param name="forceDirection">The direction that the object took damage from.</param>
        /// <param name="attacker">The GameObject that did the damage.</param>
        /// <param name="attackerObject">The object that did the damage.</param>
        /// <param name="hitCollider">The Collider that was hit.</param>
        private void OnImpact(float amount, Vector3 position, Vector3 forceDirection, GameObject attacker, object attackerObject, Collider hitCollider)
        {
            m_ImpactEvent.Invoke(amount, position, forceDirection, attacker); // limited to 4 variables for the struct??
        }

        public void OnDestroy()
        {
            EventHandler.UnregisterEvent<float, Vector3, Vector3, GameObject, object, Collider>(gameObject, "OnObjectImpact", OnImpact);
        }

        public void DebugImpactEvent(float amount, Vector3 position, Vector3 forceDirection, GameObject attacker) {
            Debug.Log("Car was attacked by " + attacker.name + " at " + position + " with force " + forceDirection + " and amount " + amount);
        }
    }
}
 
Top