(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