/// --------------------------------------------- /// Behavior Designer /// Copyright (c) Opsive. All Rights Reserved. /// https://www.opsive.com /// --------------------------------------------- namespace Opsive.BehaviorDesigner.Samples { using Opsive.BehaviorDesigner.Runtime; using Opsive.GraphDesigner.Runtime.Variables; using Opsive.Shared.Events; using UnityEngine; using UnityEngine.UI; /// /// Manages the runtime behavior scene. /// public class RuntimeBehaviorSceneManager : MonoBehaviour { [Header("Agent")] [Tooltip("A reference to the behavior tree agent.")] [SerializeField] protected GameObject m_Agent; [Tooltip("The location that the agent should train strength.")] [SerializeField] protected GameObject m_StrengthLocation; [Tooltip("The location that the agent should train speed.")] [SerializeField] protected GameObject m_SpeedLocation; [Tooltip("The location that the agent should fight.")] [SerializeField] protected GameObject m_FightLocation; [Tooltip("The left and right dumbbells.")] [SerializeField] protected GameObject[] m_Dumbbells; [Tooltip("The location the dumbbells should be equipped to.")] [SerializeField] protected GameObject[] m_DumbbellParents; [Tooltip("The location the dumbbells should be unequipped to.")] [SerializeField] protected GameObject[] m_DumbbellStorage; [Tooltip("The left and right boxing gloves.")] [SerializeField] protected GameObject[] m_BoxingGloves; [Header("Opponent")] [Tooltip("A reference to the behavior tree opponent.")] [SerializeField] protected GameObject m_Opponent; [Tooltip("The location that the opponent should fight.")] [SerializeField] protected GameObject m_OpponentFightLocation; [Tooltip("The left and right boxing gloves.")] [SerializeField] protected GameObject[] m_OpponentBoxingGloves; [Header("Camera")] [Tooltip("Specifies the camera locations.")] [SerializeField] protected GameObject[] m_CameraLocations; [Header("UI")] [Tooltip("A reference to the fight button.")] [SerializeField] protected GameObject m_FightButton; [Tooltip("A reference to the agent speed display.")] [SerializeField] protected Text m_AgentSpeed; [Tooltip("A reference to the agent strength display.")] [SerializeField] protected Text m_AgentStrength; [Tooltip("A reference to the agent health display.")] [SerializeField] protected Text m_AgentHealth; [Tooltip("A reference to the opponent health display.")] [SerializeField] protected Text m_OpponentHealth; private BehaviorTree m_AgentBehaviorTree; private BehaviorTree m_OpponentBehaviorTree; private SharedVariable m_AgentSpeedVariable; private SharedVariable m_AgentStrengthVariable; private SharedVariable m_AgentHealthVariable; private SharedVariable m_OpponentHealthVariable; /// /// Initializes the default values. /// private void Awake() { m_AgentBehaviorTree = m_Agent.GetComponent(); SetVariableValue(m_AgentBehaviorTree, "StrengthLocation", m_StrengthLocation); SetVariableValue(m_AgentBehaviorTree, "SpeedLocation", m_SpeedLocation); SetVariableValue(m_AgentBehaviorTree, "LeftDumbbell", m_Dumbbells[0]); SetVariableValue(m_AgentBehaviorTree, "RightDumbbell", m_Dumbbells[1]); SetVariableValue(m_AgentBehaviorTree, "LeftHand", m_DumbbellParents[0]); SetVariableValue(m_AgentBehaviorTree, "RightHand", m_DumbbellParents[1]); SetVariableValue(m_AgentBehaviorTree, "LeftDumbbellStorage", m_DumbbellStorage[0]); SetVariableValue(m_AgentBehaviorTree, "RightDumbbellStorage", m_DumbbellStorage[1]); SetVariableValue(m_AgentBehaviorTree, "LeftGlove", m_BoxingGloves[0]); SetVariableValue(m_AgentBehaviorTree, "RightGlove", m_BoxingGloves[1]); SetVariableValue(m_AgentBehaviorTree, "FightLocation", m_FightLocation); EventHandler.RegisterEvent(m_AgentBehaviorTree, "OnChangeToStrengthLocation", () => { SetCameraLocation(CameraLocations.Dumbbells); }); EventHandler.RegisterEvent(m_AgentBehaviorTree, "OnChangeToSpeedLocation", () => { SetCameraLocation(CameraLocations.HeavyBag); }); m_OpponentBehaviorTree = m_Opponent.GetComponent(); SetVariableValue(m_OpponentBehaviorTree, "FightLocation", m_OpponentFightLocation); SetVariableValue(m_OpponentBehaviorTree, "LeftGlove", m_OpponentBoxingGloves[0]); SetVariableValue(m_OpponentBehaviorTree, "RightGlove", m_OpponentBoxingGloves[1]); m_AgentHealth.gameObject.SetActive(false); m_OpponentHealth.gameObject.SetActive(false); // Bind the health variable value to the health display. #if UNITY_2022 var sceneVariables = Object.FindAnyObjectByType(); #else var sceneVariables = Object.FindFirstObjectByType(); #endif m_AgentSpeedVariable = sceneVariables.GetVariable("AgentSpeed"); m_AgentSpeedVariable.OnValueChange += OnAgentSpeedChanged; m_AgentStrengthVariable = sceneVariables.GetVariable("AgentStrength"); m_AgentStrengthVariable.OnValueChange += OnAgentStrengthChanged; m_AgentHealthVariable = sceneVariables.GetVariable("AgentHealth"); m_AgentHealthVariable.OnValueChange += OnAgentHealthChanged; m_OpponentHealthVariable = sceneVariables.GetVariable("OpponentHealth"); m_OpponentHealthVariable.OnValueChange += OnOpponentHealthChanged; } /// /// Sets the variable value on the specified tree. /// /// The behavior tree that should be set. /// The name of the variable. /// The value of the variable. private void SetVariableValue(BehaviorTree behaviorTree, string variableName, T value) { var sharedVariable = behaviorTree.GetVariable(variableName); sharedVariable.Value = value; } /// /// The agent's speed value changed. /// private void OnAgentSpeedChanged() { m_AgentSpeed.text = "Agent Speed: " + m_AgentSpeedVariable.Value; } /// /// The agent's strength value changed. /// private void OnAgentStrengthChanged() { m_AgentStrength.text = "Agent Strength: " + m_AgentStrengthVariable.Value; } /// /// The agent's health value changed. /// private void OnAgentHealthChanged() { m_AgentHealth.text = "Agent Health: " + Mathf.Max(m_AgentHealthVariable.Value, 0); } /// /// The agent's health value changed. /// private void OnOpponentHealthChanged() { m_OpponentHealth.text = "Opponent Health: " + Mathf.Max(m_OpponentHealthVariable.Value, 0); } /// /// Training is done. Update the subtree references so the fight tree is used. /// public void Fight() { // The dumbbells should be unequipped. m_Dumbbells[0].SetActive(false); m_Dumbbells[1].SetActive(false); m_FightButton.SetActive(false); m_AgentSpeed.gameObject.SetActive(false); m_AgentStrength.gameObject.SetActive(false); m_AgentHealth.gameObject.SetActive(true); m_OpponentHealth.gameObject.SetActive(true); // The SubtreeReferenceSelector will use the SubtreeIndex in order to determine which subtree should be chosen. SetVariableValue(m_AgentBehaviorTree, "SubtreeIndex", 1); SetVariableValue(m_OpponentBehaviorTree, "SubtreeIndex", 1); // Swap out the subtrees. m_AgentBehaviorTree.ReevaluateSubtreeReferences(); m_OpponentBehaviorTree.ReevaluateSubtreeReferences(); SetCameraLocation(CameraLocations.BoxingRing); } /// /// Specifies where the camera should be placed. /// public enum CameraLocations { HeavyBag, // The camera should look at the heavy rack. Dumbbells, // The camera should look at the dumbbell rack. BoxingRing, // The camera should look at the boxing ring. } /// /// Changes the camera location. /// /// The location the camera should be placed. private void SetCameraLocation(CameraLocations cameraLocation) { var index = (int)cameraLocation; Camera.main.transform.SetPositionAndRotation(m_CameraLocations[index].transform.position, m_CameraLocations[index].transform.rotation); } /// /// The agent has changed training locations. /// /// private void OnChangeTrainingLocations(object locationIndex) { SetCameraLocation((CameraLocations)locationIndex); } } }