popup menu refactor, player class refactor

This commit is contained in:
Vova
2023-12-17 12:01:08 +02:00
parent 72191123c2
commit 19d57651c3
10 changed files with 261 additions and 194 deletions
+5
View File
@@ -0,0 +1,5 @@
{
"recommendations": [
"visualstudiotoolsforunity.vstuc"
]
}
+10
View File
@@ -0,0 +1,10 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to Unity",
"type": "vstuc",
"request": "attach"
}
]
}
+60
View File
@@ -0,0 +1,60 @@
{
"files.exclude": {
"**/.DS_Store": true,
"**/.git": true,
"**/.vs": true,
"**/.gitmodules": true,
"**/.vsconfig": true,
"**/*.booproj": true,
"**/*.pidb": true,
"**/*.suo": true,
"**/*.user": true,
"**/*.userprefs": true,
"**/*.unityproj": true,
"**/*.dll": true,
"**/*.exe": true,
"**/*.pdf": true,
"**/*.mid": true,
"**/*.midi": true,
"**/*.wav": true,
"**/*.gif": true,
"**/*.ico": true,
"**/*.jpg": true,
"**/*.jpeg": true,
"**/*.png": true,
"**/*.psd": true,
"**/*.tga": true,
"**/*.tif": true,
"**/*.tiff": true,
"**/*.3ds": true,
"**/*.3DS": true,
"**/*.fbx": true,
"**/*.FBX": true,
"**/*.lxo": true,
"**/*.LXO": true,
"**/*.ma": true,
"**/*.MA": true,
"**/*.obj": true,
"**/*.OBJ": true,
"**/*.asset": true,
"**/*.cubemap": true,
"**/*.flare": true,
"**/*.mat": true,
"**/*.meta": true,
"**/*.prefab": true,
"**/*.unity": true,
"build/": true,
"Build/": true,
"Library/": true,
"library/": true,
"obj/": true,
"Obj/": true,
"Logs/": true,
"logs/": true,
"ProjectSettings/": true,
"UserSettings/": true,
"temp/": true,
"Temp/": true
},
"dotnet.defaultSolution": "SimUL.sln"
}
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
public abstract class BaseInteractableObject : MonoBehaviour
@@ -30,52 +31,28 @@ public abstract class BaseInteractableObject : MonoBehaviour
};
}
public InteractionStatus Interact(Player player)
public async Task<InteractionStatus> ShowPopupMenu(Player player)
{
_player = player;
PrepareMenuActions();
switch (_currentStatus)
{
case InteractionStatus.None:
var filteredActions = _menuActions.Where(x => x.Value.IsEnabled).ToDictionary(i => i.Key, i => i.Value) ;
GameManager.Instance.UI.ShowItemPopupMenu(filteredActions, PopupMenuCallback);
_currentStatus = InteractionStatus.WaitForChoose;
break;
case InteractionStatus.Complete:
_currentStatus = InteractionStatus.None;
return InteractionStatus.Complete;
default:
if (_currentStatus != InteractionStatus.WaitForChoose && _currentStatus != InteractionStatus.Complete)
{
if (_player.IsPathComplete(_interactionPoint.position))
{
InteractAction(_selectedAction);
_currentStatus = InteractionStatus.None;
return InteractionStatus.Complete;
}
else
{
_currentStatus = InteractionStatus.FarFromPlayer;
}
}
break;
}
return _currentStatus;
}
private void PopupMenuCallback(RadialMenuActions action)
{
if (action == RadialMenuActions.Cancel)
var filteredActions = _menuActions.Where(x => x.Value.IsEnabled).ToDictionary(i => i.Key, i => i.Value);
var result=await GameManager.Instance.UI.ShowItemPopupMenu(filteredActions);
if (result == RadialMenuActions.Cancel)
{
_currentStatus = InteractionStatus.Complete;
}
else
{
_selectedAction= action;
_selectedAction = result;
_currentStatus = InteractionStatus.InProgress;
}
return _currentStatus;
}
public TaskStatus Interact()
{
InteractAction(_selectedAction);
return TaskStatus.Complete;
}
protected abstract void InteractAction(RadialMenuActions interactAction);
@@ -42,14 +42,14 @@ public class InGameMouseHandler : UnityEngine.Object
if (_selectedObject != null)
{
_waypointVisual.SetWaypoint(_selectedObject._interactionPoint.position);
Player.Instance.AddTask(new PlayerTasks(Tasks.Interact, _selectedObject));
Player.Instance.Interact(_selectedObject);
}
else
{
if (Physics.Raycast(_ray, out RaycastHit hit, 100f, _walkableLayerMask))
{
_waypointVisual.SetWaypoint(hit.point);
Player.Instance.AddTask(new PlayerTasks(Tasks.Move, _waypointVisual));
Player.Instance.GoToPoint( _waypointVisual);
}
}
}
+137
View File
@@ -0,0 +1,137 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class BlockingAnimation : Attribute { }
public abstract class BaseCharacter : MonoBehaviour
{
[SerializeField]
public NavMeshAgent _navAgent;
[SerializeField]
public Animator _animator;
private const string WALK_VELOCITY = "WalkVelocity";
private readonly Queue<PlayerTasks> _tasks = new Queue<PlayerTasks>();
private PlayerTasks _currentTask;
private Action _OnAnimationFinish;
private AnimationStates _currentAnimation;
private void Update()
{
if (PlayerHelper.IsBlockingAnimation(_currentAnimation))
{
if (IsAnimationStatePlaying(0))
{
return;
}
else
{
_OnAnimationFinish?.Invoke();
_OnAnimationFinish = null;
}
}
if (_currentTask == null || _currentTask.Status == TaskStatus.Complete)
{
_tasks.TryDequeue(out _currentTask);
}
if (_currentTask != null)
{
if (_currentTask.Status == TaskStatus.Waiting)
Debug.Log($"Current task {_currentTask.Task}");
switch (_currentTask.Task)
{
case Tasks.Rotate:
_currentTask.UpdateStatus(Rotate(_currentTask.TagretObject._interactionPoint.forward));
break;
case Tasks.Move:
if (_currentAnimation == AnimationStates.Sitting)
{
SetPlayerAnimation(AnimationStates.Standing);
return;
}
_navAgent.SetDestination(_currentTask.TagretObject._interactionPoint.position);
_currentTask.UpdateStatus(MoveToPoint());
break;
case Tasks.Interact:
_currentTask.UpdateStatus(_currentTask.TagretObject.Interact());
break;
}
}
}
private TaskStatus MoveToPoint()
{
_navAgent.isStopped = false;
SetPlayerAnimation(AnimationStates.Walking);
_animator.SetFloat(WALK_VELOCITY, _navAgent.velocity.magnitude);
return IsPathComplete(_navAgent.destination) ? TaskStatus.Complete : TaskStatus.InProgress;
}
public bool IsPathComplete(Vector3 destination)
{
var dest = new Vector3(destination.x, 0, destination.z);
var pos = new Vector3(_navAgent.transform.position.x, 0, _navAgent.transform.position.z);
if (Vector3.Distance(dest, pos) <= _navAgent.radius)
{
transform.position = destination;
if (!_navAgent.hasPath || _navAgent.velocity.sqrMagnitude < 0.2f)
{
SetPlayerAnimation(AnimationStates.Idle);
_navAgent.isStopped = true;
return true;
}
}
return false;
}
public TaskStatus Rotate(Vector3 target)
{
var targetRot = Quaternion.LookRotation(target);
Quaternion rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(target), 10 * Time.deltaTime);
rotation.x = 0;
transform.rotation = rotation;
if (IsApproximate(targetRot, transform.rotation, 0.000004f))
{
return TaskStatus.Complete;
}
return TaskStatus.InProgress;
}
protected void AddTask(PlayerTasks task)
{
_tasks.Enqueue(task);
}
public bool IsAnimationStatePlaying(int animLayer)
{
string stateName = PlayerHelper.GetEnumMemberValue(_currentAnimation);
var stateInfo = _animator.GetCurrentAnimatorStateInfo(animLayer);
return stateInfo.IsName(stateName) && stateInfo.normalizedTime < 1.0f;
}
public void SetPlayerAnimation(AnimationStates newState, Action onAnimationFinish)
{
_OnAnimationFinish = onAnimationFinish;
SetPlayerAnimation(newState);
}
public void SetPlayerAnimation(AnimationStates newState)
{
if (newState == _currentAnimation)
{
return;
}
_animator.Play(PlayerHelper.GetEnumMemberValue(newState));
_currentAnimation = newState;
}
private bool IsApproximate(Quaternion q1, Quaternion q2, float precision)
{
return Mathf.Abs(Quaternion.Dot(q1, q2)) >= 1 - precision;
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ae6d3e3aea34ae447a6aa1914a953e8e
+15 -140
View File
@@ -1,38 +1,23 @@
using Assets.Scripts.Interfaces;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class BlockingAnimation : Attribute { }
public class Player : MonoBehaviour
public class Player : BaseCharacter
{
public static Player Instance { get; private set; }
[SerializeField]
public NavMeshAgent _navAgent;
[SerializeField]
public Animator _animator;
[SerializeField]
private Transform _holdPoint;
private PlayerStates _currentActing;
private AnimationStates _currentAnimation;
public Dictionary<StatsId, object> Stats;
public JobPositions JobPosition { get; set; }
public EducationSkill Education { get; set; }
private readonly Queue<PlayerTasks> _tasks = new Queue<PlayerTasks>();
private PlayerTasks _currentTask;
private const string WALK_VELOCITY = "WalkVelocity";
private ContainerItem _containerItem;
private Action _OnAnimationFinish;
private string _locationName;
private void Awake()
@@ -66,142 +51,32 @@ public class Player : MonoBehaviour
GameManager.Instance.Time.OnMinuteChanged -= UpdateStatsByClock;
}
private void Update()
{
if (PlayerHelper.IsBlockingAnimation(_currentAnimation))
{
if (IsAnimationStatePlaying(0))
{
return;
}
else
{
_OnAnimationFinish?.Invoke();
_OnAnimationFinish = null;
}
}
if (_currentTask == null || _currentTask.Status == TaskStatus.Complete)
{
_tasks.TryDequeue(out _currentTask);
}
if (_currentTask != null)
{
if (_currentTask.Status == TaskStatus.Waiting)
Debug.Log($"Current task {_currentTask.Task}");
switch (_currentTask.Task)
{
case Tasks.Rotate:
_currentTask.UpdateStatus(Rotate(_currentTask.TagretObject._interactionPoint.forward));
break;
case Tasks.Move:
if (_currentAnimation == AnimationStates.Sitting)
{
SetPlayerAnimation(AnimationStates.Standing);
return;
}
_navAgent.SetDestination(_currentTask.TagretObject._interactionPoint.position);
_currentTask.UpdateStatus(MoveToPoint());
break;
case Tasks.Interact:
var result = _currentTask.TagretObject.Interact(this);
switch (result)
{
case InteractionStatus.FarFromPlayer:
AddTask(new PlayerTasks(Tasks.Move, _currentTask.TagretObject));
AddTask(new PlayerTasks(Tasks.Rotate, _currentTask.TagretObject));
AddTask(_currentTask);
_currentTask = null;
break;
case InteractionStatus.Complete:
_currentTask.UpdateStatus(TaskStatus.Complete);
break;
default:
break;
}
break;
}
}
}
public void SetPosition(Vector3 desiredPosition)
{
_navAgent.Warp(desiredPosition);
_navAgent.updatePosition = false;
}
private TaskStatus MoveToPoint()
public void GoToPoint(BaseInteractableObject point)
{
_navAgent.isStopped = false;
SetPlayerAnimation(AnimationStates.Walking);
_animator.SetFloat(WALK_VELOCITY, _navAgent.velocity.magnitude);
return IsPathComplete(_navAgent.destination) ? TaskStatus.Complete : TaskStatus.InProgress;
AddTask(new PlayerTasks(Tasks.Move, point));
}
public bool IsPathComplete(Vector3 destination)
public async void Interact(BaseInteractableObject interactionItem)
{
var dest = new Vector3(destination.x, 0, destination.z);
var pos = new Vector3(_navAgent.transform.position.x, 0, _navAgent.transform.position.z);
if (Vector3.Distance(dest, pos) <= _navAgent.radius)
var result = await interactionItem.ShowPopupMenu(this);
if (result != InteractionStatus.Complete)
{
transform.position = destination;
if (!_navAgent.hasPath || _navAgent.velocity.sqrMagnitude < 0.2f)
if (!IsPathComplete(interactionItem._interactionPoint.position))
{
SetPlayerAnimation(AnimationStates.Idle);
_navAgent.isStopped = true;
return true;
AddTask(new PlayerTasks(Tasks.Move, interactionItem));
AddTask(new PlayerTasks(Tasks.Rotate, interactionItem));
AddTask(new PlayerTasks(Tasks.Interact, interactionItem));
}
else
{
AddTask(new PlayerTasks(Tasks.Interact, interactionItem));
}
}
return false;
}
public TaskStatus Rotate(Vector3 target)
{
var targetRot = Quaternion.LookRotation(target);
Quaternion rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(target), 10 * Time.deltaTime);
rotation.x = 0;
transform.rotation = rotation;
if (IsApproximate(targetRot, transform.rotation, 0.000004f))
{
return TaskStatus.Complete;
}
return TaskStatus.InProgress;
}
private bool IsApproximate(Quaternion q1, Quaternion q2, float precision)
{
return Mathf.Abs(Quaternion.Dot(q1, q2)) >= 1 - precision;
}
public void SetPlayerAnimation(AnimationStates newState, Action onAnimationFinish)
{
_OnAnimationFinish = onAnimationFinish;
SetPlayerAnimation(newState);
}
public void SetPlayerAnimation(AnimationStates newState)
{
if (newState == _currentAnimation)
{
return;
}
_animator.Play(PlayerHelper.GetEnumMemberValue(newState));
_currentAnimation = newState;
}
public bool IsAnimationStatePlaying(int animLayer)
{
string stateName = PlayerHelper.GetEnumMemberValue(_currentAnimation);
var stateInfo = _animator.GetCurrentAnimatorStateInfo(animLayer);
return stateInfo.IsName(stateName) && stateInfo.normalizedTime < 1.0f;
}
public void AddTask(PlayerTasks task)
{
_tasks.Enqueue(task);
}
public void SetPlayerActing(PlayerStates state)
+11 -11
View File
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
@@ -9,47 +9,47 @@ public class RadialMenuItem : MonoBehaviour
{
[SerializeField]
private Button _radialMenuItemPrefab;
private Action<RadialMenuActions> _menuButtonClick=null;
private Dictionary<RadialMenuActions, RadialMenuActionDescription> _actions;
TaskCompletionSource<RadialMenuActions> tcs = new TaskCompletionSource<RadialMenuActions>();
public void ShowButtons(RadialMenuItem popupMenu, Dictionary<RadialMenuActions, RadialMenuActionDescription> actions, Action<RadialMenuActions> menuButtonClick)
public Task<RadialMenuActions> ShowButtons(RadialMenuItem popupMenu, Dictionary<RadialMenuActions, RadialMenuActionDescription> actions)
{
_actions = actions;
_menuButtonClick = menuButtonClick;
for (int buttonsCount = 0; buttonsCount < actions.Count; buttonsCount++)
{
var button = Instantiate(_radialMenuItemPrefab);
button.transform.SetParent(transform, false);
float theta = (2 * Mathf.PI / actions.Count) * buttonsCount;
float posX=Mathf.Sin(theta);
float posY=Mathf.Cos(theta);
float posX = Mathf.Sin(theta);
float posY = Mathf.Cos(theta);
button.transform.localPosition = new Vector3(posX, posY, 0)*100f;
button.transform.localPosition = new Vector3(posX, posY, 0) * 100f;
var textMeshPro = button.GetComponentInChildren<TextMeshProUGUI>();
if (textMeshPro != null)
{
textMeshPro.text = actions.ElementAt(buttonsCount).Value.Description;
}
AddEvent(button, buttonsCount);
}
return tcs.Task;
}
void AddEvent(Button b, int buttonNumber)
{
b.onClick.AddListener(() =>
{
tcs.SetResult(_actions.ElementAt(buttonNumber).Key);
Close();
_menuButtonClick?.Invoke(_actions.ElementAt(buttonNumber).Key);
});
}
public void CancelAndClose()
{
Close();
_menuButtonClick?.Invoke(RadialMenuActions.Cancel);
}
private void Close()
+3 -2
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
public class UISystem : MonoBehaviour
@@ -32,12 +33,12 @@ public class UISystem : MonoBehaviour
jobSelector.ShowJobSelectionDialog(title, onCancel, onConfirm);
}
public void ShowItemPopupMenu(Dictionary<RadialMenuActions, RadialMenuActionDescription> actions,Action<RadialMenuActions> itemsMenuCallback)
public async Task<RadialMenuActions> ShowItemPopupMenu(Dictionary<RadialMenuActions, RadialMenuActionDescription> actions)
{
_popupMenu = Instantiate(_radialMenuItemPrefab);
_popupMenu.transform.transform.SetParent(transform, false);
_popupMenu.transform.position = Input.mousePosition;
_popupMenu.ShowButtons(_popupMenu, actions,itemsMenuCallback);
return await _popupMenu.ShowButtons(_popupMenu, actions);
}
public void ClosePopupMenu()