This repository has been archived on 2025-04-11. You can view files and clone it, but cannot push or open issues or pull requests.
project-undercover/Project Undercover/Assets/Scripts/CharacterStateMachine/StateController.cs
2017-10-08 18:37:19 -05:00

235 lines
6.6 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class StateController : SelectableObject
{
public State currentState;
public State remainState;
public static readonly float INTERACT_RANGE = 1.5f;
[HideInInspector] public NavMeshAgent navMeshAgent;
[HideInInspector] public Animator animator;
[HideInInspector] public CharacterAnimator characterAnimator;
// Object Selector properties
private SelectableObject _selectedObject;
private Interaction _selectedInteraction;
private Coroutine _roamCoroutine;
private static float _startInteractionProgressLimit = 0.3f;
private static float _endInteractionProgressLimit = 0.8f;
void Awake()
{
navMeshAgent = GetComponent<NavMeshAgent>();
if (!photonView.isMine)
{
navMeshAgent.obstacleAvoidanceType = ObstacleAvoidanceType.NoObstacleAvoidance;
navMeshAgent.updateRotation = false;
}
animator = GetComponent<Animator>();
characterAnimator = GetComponent<CharacterAnimator>();
}
public void Start()
{
if (photonView.isMine)
currentState.DoStartActions(this);
}
public override void Update()
{
if (photonView.isMine)
{
currentState.UpdateState(this);
}
}
public void TransitionToState(State nextState)
{
if (nextState != remainState)
{
currentState.DoEndActions(this);
currentState = nextState;
currentState.DoStartActions(this);
}
}
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
if (stream.isWriting)
{
stream.SendNext(Destination);
stream.SendNext(navMeshAgent.stoppingDistance);
}
else
{
Destination = (Vector3)stream.ReceiveNext();
navMeshAgent.stoppingDistance = (float)stream.ReceiveNext();
}
}
public Vector3 Destination
{
get
{
return navMeshAgent.destination;
}
set
{
navMeshAgent.destination = value;
}
}
// Initiates interaction with other StateController
public void InitiateInteractionWithSelectedObject()
{
if (SelectedObject == this)
Debug.LogError("Attempted to set interactor as self");
if (SelectedObject.IsInteracting)
Debug.Log(SelectedObject.name + " is busy and cannot interact with " + name);
// Debug.Log("Sending interaction request...");
IsInteracting = true;
SelectedObject.Interactor = this;
}
public SelectableObject SelectedObject
{
get
{
return _selectedObject;
}
set
{
if (_selectedObject != null)
_selectedObject.Deselected();
_selectedObject = value;
if (_selectedObject != null)
{
_selectedObject.Selected();
navMeshAgent.stoppingDistance = INTERACT_RANGE * 0.8f;
}
else
{
navMeshAgent.stoppingDistance = 0.0f;
Destination = transform.position;
}
}
}
public override string GetInteractionTitle()
{
return name;
}
public static Vector3 GetRandomLocation()
{
float roomSize = 10.0f;
var randTarget = new Vector3(roomSize - (roomSize * 2 * UnityEngine.Random.value), 0.0f, roomSize - (roomSize * 2 * UnityEngine.Random.value));
NavMeshHit hit;
if (NavMesh.SamplePosition(randTarget, out hit, 1.0f, NavMesh.AllAreas))
return hit.position;
else
return GetRandomLocation();
}
public bool IsInteractionAccepted()
{
return IsInteracting && SelectedObject.IsInteracting && SelectedObject.Interactor == this;
}
public bool IsInteractionRejected()
{
return SelectedObject.Interactor != this;
}
public void FinishInteraction()
{
if (IsInteracting)
IsInteracting = false;
if (SelectedObject)
{
if (SelectedObject.IsInteracting)
SelectedObject.IsInteracting = false;
SelectedObject = null;
}
}
public Interaction SelectedInteraction
{
get
{
return _selectedInteraction;
}
set
{
_selectedInteraction = value;
}
}
public void StartRoaming()
{
_roamCoroutine = StartCoroutine(Roam());
}
public void StopRoaming()
{
StopCoroutine(_roamCoroutine);
}
private IEnumerator Roam()
{
while (true)
{
yield return new WaitForSeconds(UnityEngine.Random.value * 10.0f);
Destination = GetRandomLocation();
}
}
public void FaceSelectedObject()
{
float progress = animator.GetCurrentAnimatorStateInfo(0).normalizedTime;
Vector3 otherPos = SelectedObject.transform.position;
float initialRotation = SelectedInteraction.initialRotation;
SetFacingRotation(otherPos, progress, initialRotation);
}
public void FaceInteractor()
{
if (Interactor == null)
Debug.LogError("Cannot face a null Interactor");
float progress = Interactor.animator.GetCurrentAnimatorStateInfo(0).normalizedTime;
Vector3 otherPos = Interactor.transform.position;
if (Interactor.SelectedInteraction == null)
return;
float initialRotation = Interactor.SelectedInteraction.objectInitialRotation;
SetFacingRotation(otherPos, progress, initialRotation);
}
private void SetFacingRotation(Vector3 otherPos, float progress, float initialRotation)
{
if (progress > _startInteractionProgressLimit && progress < _endInteractionProgressLimit)
return;
Vector3 pos = transform.position;
Vector3 facingDirection = (otherPos - pos).normalized;
Quaternion facingRotation = Quaternion.FromToRotation(Vector3.forward, facingDirection);
if (progress < _startInteractionProgressLimit)
{
Quaternion adjustedRotation = facingRotation * Quaternion.Euler(0, initialRotation, 0);
transform.rotation = Quaternion.Slerp(transform.rotation, adjustedRotation, Time.deltaTime * 5.0f);
}
else
{
transform.rotation = Quaternion.Slerp(transform.rotation, facingRotation, Time.deltaTime * 5.0f);
}
}
}