这是第一个 Unity 开放项目的repo,是 Unity 和社区合作创建的一个小型开源游戏演示,第一款游戏是一款名为 Chop Chop 的动作冒险游戏。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

180 行
5.5 KiB

using System.Collections.Generic;
using UnityEngine;
public enum InteractionType { None = 0, PickUp, Cook, Talk };
public class InteractionManager : MonoBehaviour
{
[HideInInspector] public InteractionType currentInteraction;
[SerializeField] private InputReader _inputReader = default;
//To store the object we are currently interacting with
private LinkedList<Interaction> _ongoingInteractions = new LinkedList<Interaction>();
//Events for the different interaction types
[Header("Broadcasting on")]
[SerializeField] private ItemEventChannelSo _onObjectPickUp = default;
[SerializeField] private VoidEventChannelSO _onCookingStart = default;
[SerializeField] private DialogueEventChannelSo _startTalking = default;
//UI event
[SerializeField] private InteractionUIEventChannelSO _toggleInteractionUI = default;
[Header("Listening to")]
//Check if the interaction ended
[SerializeField] private VoidEventChannelSO _onInteractionEnded = default;
[SerializeField] private VoidEventChannelSO _oninteractionResponsed = default;
private void OnEnable()
{
_inputReader.interactEvent += OnInteractionButtonPress;
_oninteractionResponsed.OnEventRaised += OnInteractionResponseActivated;
_onInteractionEnded.OnEventRaised += OnInteractionEnd;
}
private void OnDisable()
{
_inputReader.interactEvent -= OnInteractionButtonPress;
_oninteractionResponsed.OnEventRaised -= OnInteractionResponseActivated;
_onInteractionEnded.OnEventRaised -= OnInteractionEnd;
}
//When the interaction ends, we still want to display the interaction UI if we are still in the trigger zone
void OnInteractionEnd()
{
_inputReader.EnableGameplayInput();
Interaction onGoingInteraction = _ongoingInteractions.First.Value;
switch (onGoingInteraction.Type)
{
//we show it after cooking or talking, in case player want to interact again
case InteractionType.Cook:
case InteractionType.Talk:
_toggleInteractionUI.RaiseEvent(true, onGoingInteraction.Type);
Debug.Log("Display interaction UI");
break;
default:
break;
}
}
// interaction button press event handler activated by the StateMachine
void OnInteractionResponseActivated()
{
//remove interaction after press
Interaction onGoingInteraction = _ongoingInteractions.Count > 0 ?
_ongoingInteractions.First.Value : Interaction.NONE;
_toggleInteractionUI.RaiseEvent(false, onGoingInteraction.Type);
switch (onGoingInteraction.Type)
{
case InteractionType.None:
return;
case InteractionType.PickUp:
GameObject itemObject = onGoingInteraction.InteractableObject;
_ongoingInteractions.RemoveFirst();
if (_onObjectPickUp != null)
{
//raise an event with an item as parameter (to add object to inventory)
Item currentItem = itemObject.GetComponent<CollectibleItem>().GetItem();
_onObjectPickUp.RaiseEvent(currentItem);
//Debug.Log("PickUp event raised");
}
//destroy the GO
Destroy(itemObject);
break;
case InteractionType.Cook:
if (_onCookingStart != null)
{
_onCookingStart.RaiseEvent();
//Debug.Log("Cooking event raised");
//Change the action map
_inputReader.EnableMenuInput();
//set current interaction for state machine
}
break;
case InteractionType.Talk:
if (_startTalking != null)
{
//raise an event with an actor as parameter
//Actor currentActor = currentInteractableObject.GetComponent<Dialogue>().GetActor();
//_startTalking.RaiseEvent(currentActor);
//Debug.Log("talk event raised");
//Change the action map
_inputReader.EnableDialogueInput();
//set current interaction for state machine
}
break;
default:
break;
}
}
void OnInteractionButtonPress()
{
Interaction onGoingInteraction = _ongoingInteractions.Count > 0 ?
_ongoingInteractions.First.Value : Interaction.NONE;
//set current interaction for state machine
if (onGoingInteraction.Type != InteractionType.None)
{
currentInteraction = onGoingInteraction.Type;
}
}
private void OnTriggerEnter(Collider other)
{
InteractionType ongoingInteractionType = InteractionType.None;
if (other.CompareTag("Pickable"))
{
ongoingInteractionType = InteractionType.PickUp;
//Debug.Log("I triggered a pickable object!");
}
else if (other.CompareTag("CookingPot"))
{
ongoingInteractionType = InteractionType.Cook;
//Debug.Log("I triggered a cooking pot!");
}
else if (other.CompareTag("NPC"))
{
ongoingInteractionType = InteractionType.Talk;
//Debug.Log("I triggered an NPC!");
}
if (ongoingInteractionType != InteractionType.None)
{
_ongoingInteractions.AddFirst(new Interaction(ongoingInteractionType, other.gameObject));
DisplayInteractionUI();
}
}
private void DisplayInteractionUI()
{
//Raise event to display UI
Interaction onGoingInteraction = _ongoingInteractions.First.Value;
_toggleInteractionUI.RaiseEvent(true, onGoingInteraction.Type);
}
private void OnTriggerExit(Collider other)
{
ResetInteraction(other.gameObject);
}
private void ResetInteraction(GameObject obj)
{
LinkedListNode<Interaction> currentNode = _ongoingInteractions.First;
while (currentNode != null)
{
if (currentNode.Value.InteractableObject == obj)
{
_ongoingInteractions.Remove(currentNode);
break;
}
currentNode = currentNode.Next;
}
if (_ongoingInteractions.Count > 0)
{
_toggleInteractionUI.RaiseEvent(true, _ongoingInteractions.First.Value.Type);
}
else
{
_toggleInteractionUI.RaiseEvent(false, InteractionType.None);
}
}
}