// Animancer // Copyright 2020 Kybernetik //
#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value.
using Animancer.Examples.StateMachines.Brains;
using Animancer.FSM;
using UnityEngine;
namespace Animancer.Examples.AnimatorControllers
{
///
/// A which allows the player to play golf using the
/// script.
///
[AddComponentMenu(Strings.MenuPrefix + "Examples/Hybrid - Golf Mini Game")]
[HelpURL(Strings.APIDocumentationURL + ".Examples.AnimatorControllers/GolfMiniGame")]
public sealed class GolfMiniGame : CreatureBrain
{
/************************************************************************************************************************/
[SerializeField] private Events.GolfHitController _GolfHitController;
[SerializeField] private Transform _GolfClub;
[SerializeField] private Transform _ExitPoint;
[SerializeField] private GameObject _RegularControls;
[SerializeField] private GameObject _GolfControls;
private Vector3 _GolfClubStartPosition;
private Quaternion _GolfClubStartRotation;
private CreatureBrain _PreviousBrain;
private enum State { Entering, Turning, Playing, Exiting, }
private State _State;
/************************************************************************************************************************/
private void Awake()
{
_GolfClubStartPosition = _GolfClub.localPosition;
_GolfClubStartRotation = _GolfClub.localRotation;
}
/************************************************************************************************************************/
///
/// When a enters this trigger, try to make it enter this state.
///
private void OnTriggerEnter(Collider collider)
{
if (enabled)
return;
var creature = collider.GetComponent();
if (creature == null ||
!creature.Idle.TryEnterState())
return;
_State = State.Entering;
_PreviousBrain = creature.Brain;
Creature = creature;
}
/************************************************************************************************************************/
private void FixedUpdate()
{
switch (_State)
{
case State.Entering:
if (MoveTowards(_GolfHitController.transform.position))
StartTurning();
break;
case State.Turning:
if (Quaternion.Angle(Creature.Animancer.transform.rotation, _GolfHitController.transform.rotation) < 1)
StartPlaying();
break;
case State.Playing:
break;
case State.Exiting:
if (MoveTowards(_ExitPoint.position))
Creature.Brain = _PreviousBrain;
break;
}
}
/************************************************************************************************************************/
private bool MoveTowards(Vector3 destination)
{
var step = Creature.Stats.GetMoveSpeed(false) * Time.deltaTime;
var direction = destination - Creature.Rigidbody.position;
var distance = direction.magnitude;
MovementDirection = direction / distance;// Normalize.
return distance <= step;
}
/************************************************************************************************************************/
private void StartTurning()
{
_State = State.Turning;
MovementDirection = _GolfHitController.transform.forward;
// Disable the Creature's movement and move them next to the golf ball.
Creature.Rigidbody.velocity = Vector3.zero;
Creature.Rigidbody.isKinematic = true;
Creature.Rigidbody.position = _GolfHitController.transform.position;
}
/************************************************************************************************************************/
private void StartPlaying()
{
_State = State.Playing;
// Put the GolfClub in their hand, specifically as a child of the "Holder.R" object which is positioned
// correctly for holding objects.
var rightHand = Creature.Animancer.Animator.GetBoneTransform(HumanBodyBones.RightHand);
rightHand = rightHand.Find("Holder.R");
_GolfClub.parent = rightHand;
_GolfClub.localPosition = Vector3.zero;
_GolfClub.localRotation = Quaternion.identity;
// Activate the GolfHitController so it can now take control of the creature.
_GolfHitController.gameObject.SetActive(true);
// Swap the displayed controls.
_RegularControls.SetActive(false);
_GolfControls.SetActive(true);
}
/************************************************************************************************************************/
public void Quit()
{
// Basically just undo everything StartTurning and StartPlaying did.
_State = State.Exiting;
_GolfHitController.gameObject.SetActive(false);
_RegularControls.SetActive(true);
_GolfControls.SetActive(false);
_GolfClub.parent = transform;
_GolfClub.localPosition = _GolfClubStartPosition;
_GolfClub.localRotation = _GolfClubStartRotation;
Creature.Rigidbody.isKinematic = false;
// The creature will still be in the Idle state from when the mini game started.
// But it only plays its animation when first entered so we force the creature to re-enter that state.
Creature.Idle.TryReEnterState();
}
/************************************************************************************************************************/
}
}