(Archive) Interaction Detection

Reason: 05/01/2024 I'm doing a rewrite of InteractionDetection to simplify logic and move optimizations. Note, BuildItem handling code have been removed, however, they can be found in the archive here.

using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using Mirror;
using UnityEngine.SceneManagement;
using Rewired;
public class InteractionDetection : NetworkBehaviour
{
    #region Const Defines
    public static Vector3 CENTER_VECTOR = new Vector3(0.5F, 0.5F, 0F);
    public const float REACH = 4.0F;
    public const string INTERACT = "Interact";
    #endregion
    Rewired.Player RPlayer;
    public LayerMask layerMask;
    [Header("Audio")]
    public AudioClip buildItemPickUpAudio;
    public Camera cam;
    public bl_UCrosshairInfo crosshair;
    public GameObject c_normal;
    public GameObject c_interact;

    public HostManagerUI hmUI;
    public bool crosshair_enabled;
    public GameObject mInventoryFullDisplay;
    [Header("FSM Controls")]
    public PlayMakerFSM[] input_disable_fsm;

    //Runtime
    private bool mInReach;
    private GameObject mSelected;
    private Outline mHostMachineOutline;
    private EquipmentManager mEquipmentManager;
    private Player mPlayer;
    public override void OnStartLocalPlayer()
    {
        base.OnStartLocalPlayer();
        RPlayer = ReInput.players.GetPlayer(0);
        EnablePlayerUI();
        mEquipmentManager = GetComponent<EquipmentManager>();
        mPlayer = GetComponent<Player>();
    }

    #region Getters
    public GameObject GetSelected()
    {
        return mSelected;
    }
    #endregion

    private void OnDisable()
    {
        //Disable UI crosshair on disable
        crosshair.gameObject.SetActive(false);
    }
    void Update()
    {
        //For non-local player, simply disable behaviour to stop Update() from running
        if (!isLocalPlayer)
        {
            enabled = false;
            return;
        }

        mInventoryFullDisplay.SetActive(false);

        if (mInReach)
        {
            if (crosshair_enabled)
            {
                c_normal.SetActive(false);
                c_interact.SetActive(true);
            }

        }
        else if (!mInReach && crosshair_enabled)
        {
            c_interact.SetActive(false);
            c_normal.SetActive(true);
        }
        // Set origin of ray to 'center of screen' and direction of ray to 'camera view'
        Ray ray = cam.ViewportPointToRay(CENTER_VECTOR);

        RaycastHit hit; // Variable reading information about the collider hit

        // Cast ray from center of the screen towards where the player is looking
        //Do not apply layer mask to Raycast since we must check for potential blocking by everything. Validate layer inside Raycast.
        if (Physics.Raycast(ray, out hit, REACH) && (layerMask & (1 << hit.collider.gameObject.layer)) != 0)
        {
            if (hit.collider.tag == "Interactable")
            {
                mInReach = true;
                if (!mPlayer.is_alive && SceneManager.GetActiveScene().name != "Lobby")
                {
                    crosshair.SetColor(Color.red);
                    return;
                }
                crosshair.SetDefaultColors();
                if (mSelected == null || mSelected != hit.collider.gameObject)
                {
                    mSelected = hit.collider.gameObject;
                }

                if (mSelected.GetComponent<Interactable>() != null)
                {
                    var visualType = mSelected.GetComponent<Interactable>().visualType;
                    if (visualType == Interactable.VisualType.Interactable)
                    {
                        crosshair.SetDefaultColors();
                    }
                    else if (visualType == Interactable.VisualType.Non_Interactable)
                    {
                        crosshair.SetColor(Color.red);
                    }
                }


                if (RPlayer.GetButtonDown(INTERACT))
                {
                    if (mSelected.GetComponent<Interactable>() != null)
                    {
                        mSelected.GetComponent<Interactable>().Interact();
                        return;
                    }
                    //Door
                    if (mSelected.GetComponent<Door>() != null)
                    {
                        mSelected.GetComponent<Door>().Interact();
                        return;
                    }
                    else if (mSelected.GetComponentInParent<Door>() != null)
                    {
                        mSelected.GetComponentInParent<Door>().Interact();
                        return;
                    }
                    //pickup
                    BuildItem b = mSelected.GetComponent<BuildItem>();
                    if (b != null && b.isPickupMode)
                    {
                        RPlayer.SetVibration(1, 0.5f, 0.2f);
                        b.GetComponent<BuildItem>().PickUp();
                        mEquipmentManager.LocalPlay2DAudio(buildItemPickUpAudio, 0.25f, false, 0);
                        return;
                    }

                    //Send message
                    mSelected.SendMessage(INTERACT);
                }

            }
            else if (hit.collider.tag == "HostMachine" && hit.collider.gameObject.GetComponent<HostMachine>().mIsDiscoveredAllTiemframe)
            {
                mInReach = true;
                if (!mPlayer.is_alive || !mEquipmentManager.canUse)
                {
                    crosshair.SetColor(Color.red);
                    return;
                }

                crosshair.SetDefaultColors();

                //Shift to EquipmentManager
                if (mSelected == null || mSelected != hit.collider.gameObject)
                {

                    mSelected = hit.collider.gameObject;
                }


                //Enable phone showhand
                /*this.GetComponent<Phone>().interactable = true;
                this.GetComponent<Phone>().host_machine = hit.collider.transform.GetComponent<HostMachine>();
                this.GetComponent<Phone>().RefreshSelectedHM();
                */

                //Above commented for shift to EquipmentManager

                //Handle Outline (Different for host/player by destory or check) Only host can see outline
                //Disable for outline glitch, outline only visble when object is non-visble to killer
                if (hit.collider.gameObject.GetComponent<Outline>() != null && hit.collider.gameObject.GetComponent<Outline>().enabled)
                {
                    mHostMachineOutline = hit.collider.gameObject.GetComponent<Outline>();
                    mHostMachineOutline.enabled = false;
                }

                HostMachine hm = hit.collider.gameObject.GetComponent<HostMachine>();
                hmUI.DisplayProgressBar(hm.max_health - hm.machine_Health, hm.max_health);
            }
            else if (hit.collider.tag == "Equipment" && hit.collider.GetComponent<Equipment>().GetCanPickUp())
            {
                mInReach = true;

                //For past equipment, we want to show as if nothing is there thus in reach = false
                if (BaseTimeframeManager.Instance.GetIsPastLocal())
                {
                    mInReach = false;
                    return;
                }

                //04/17/2024 - If equipment inventory is full, then show red crosshair as indication
                if (!mEquipmentManager.canUse || mEquipmentManager.GetIsPlayerCarryInventoryFull())
                {
                    mInventoryFullDisplay.SetActive(true);
                    crosshair.SetColor(Color.red);
                    return;
                }

                crosshair.SetDefaultColors();
                if (mSelected == null || mSelected != hit.collider.gameObject)
                {

                    mSelected = hit.collider.gameObject;
                }
                //Equipment
                if (RPlayer.GetButtonDown(INTERACT))
                {
                    RPlayer.SetVibration(1, 0.5f, 0.2f);
                    mEquipmentManager.PickUpEquipment(hit.collider.gameObject.GetComponent<Equipment>());
                }

            }
            else if (hit.collider.tag == "PlacedObject")
            {
                mInReach = true;
                if (!mEquipmentManager.canUse)
                {
                    crosshair.SetColor(Color.red);
                    return;
                }
                crosshair.SetDefaultColors();
            }

            ////[DEBUG] Remove for build, testing only
            //else if (hit.collider.tag == "Tree")
            //{
            //    if (RPlayer.GetButtonDown("Fire"))
            //    {
            //        hit.collider.gameObject.SendMessage("Damage", 100);
            //    }
            //}

            else
            {
                mInReach = false;
                if (mSelected != null)
                {
                    mSelected?.GetComponent<Interactable>()?.UnSelect();
                }
                mSelected = null;
                //Handle Outline (Different for host/player by destory or check) Only host can see outline
                if (mHostMachineOutline != null)
                {
                    mHostMachineOutline.enabled = true;
                }
                hmUI.HideProgressBar();

            }
        }

        else
        {
            mInReach = false;
            if (mSelected != null)
            {
                mSelected?.GetComponent<Interactable>()?.UnSelect();
            }
            mSelected = null;
            //Handle Outline (Different for host/player by destory or check) Only host can see outline
            if (mHostMachineOutline != null)
            {
                mHostMachineOutline.enabled = true;
            }
            hmUI.HideProgressBar();

        }
    }


    //Player Control States
    public void DisablePlayerControl() // May not work, check before use
    {
        foreach (var component in input_disable_fsm)
        {
            component.enabled = false;
        }
    }
    public void EnablePlayerControl() // May not work, check before use
    {
        foreach (var component in input_disable_fsm)
        {
            component.enabled = true;
        }
    }
    public void DisablePlayerUI()
    {
        crosshair_enabled = false;
        CursorManager.Instance.UnLockCursor();
        c_interact.SetActive(false);
        c_normal.SetActive(false);
    }
    public void EnablePlayerUI()
    {
        crosshair_enabled = true;
        CursorManager.Instance.LockCursor();
        c_interact.SetActive(true);
        c_normal.SetActive(true);
    }
}

Last updated