Паттерн Стратегия в Unity. Как всунуть логику движения по клику в этот паттерН?
Есть 3 класса, абстрактный Human и производные от него Player и Enemy (Enemy еще даже не пытался делать). По итогу на сцене мой игрок уползает в сторону, а на клики вообще не реагирует, хотя если писать логику прям в классе Player то всё работает. Извините если это выглядит слишком глупо.
Класс Human
using UnityEngine;
namespace Assets
{
public abstract class Human : MonoBehaviour
{
protected readonly byte maxHealth = 100;
protected string humanName;
protected byte currentHealth;
private IWalkToClick walkToClickBehaviour;
//Поведение для интерфейса по клику
public void SetWalkToClickBehaviour(IWalkToClick behaviour) => walkToClickBehaviour = behaviour;
public void PerformClickTomove() => walkToClickBehaviour.MoveToClick();
public void PerformLocatePositionFromClick() => walkToClickBehaviour.LocatePosition();
}
}
Класс Игрока Player
using UnityEngine;
namespace Assets
{
public class Player : Human
{
public CharacterController Controller;
private Vector3 StartPosition;
[System.Serializable]
public struct PlayerInfo
{
public Vector3 position;
public PlayerInfo(Vector3 position)
{
this.position = position;
}
}
[SerializeField]
private Vector3 direction;
private PlayerInfo playerInfo;
private void Start()
{
playerInfo = new PlayerInfo(transform.position);
StartPosition = transform.position;
SetWalkToClickBehaviour(new HumanWalkToClick(Controller, transform, .25f));
}
private void Update()
{
if (Input.GetKey(KeyCode.Space))
{
LocatePosition();
}
Movement();
}
private void LocatePosition()
{
PerformLocatePositionFromClick();
}
private void Movement()
{
PerformClickTomove();
}
}
}
Интерфейс для реализации в классе
using UnityEngine;
namespace Assets
{
public interface IWalkToClick
{
void LocatePosition();
void MoveToClick();
}
}
Класс с реализацией передвижения
using UnityEngine;
namespace Assets
{
public class HumanWalkToClick : IWalkToClick
{
private Vector3 StartPosition;
private Transform HumanTransform;
private float Speed;
private CharacterController Controller;
public HumanWalkToClick(CharacterController controller,Transform humanTransform,float speed)
{
Controller = controller;
HumanTransform = humanTransform;
Speed = speed;
}
public void LocatePosition()
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, 1000))
{
//Выясням куда кликнул пользователь
StartPosition = new Vector3(hit.point.x, hit.point.y, hit.point.z);
}
}
public void MoveToClick()
{
//Если расстояние между объектом и позицией клика больше 1, то двигаемся к точке
if (Vector3.Distance(HumanTransform.position, StartPosition) > 1)
{
Quaternion newRotation = Quaternion.LookRotation(StartPosition - HumanTransform.position, Vector3.forward);
newRotation.z = 0f;
newRotation.x = 0f;
HumanTransform.rotation = Quaternion.Slerp(HumanTransform.rotation, newRotation, Time.deltaTime * 10);
Controller.SimpleMove(HumanTransform.forward * Speed);
}
else
{
//Что делаем если расстояние между объектом и нужной точкой меньше 1
}
}
}
}
Ответы (1 шт):
У вас сломанная архитектура классов. Классов Player и Enemy не должно быть, потому что они у вас не отличаются.
Есть сущность "Human", который я бы назвал "Unit", поскольку под ней может быть и гоблин и черт лысый по желанию, "Human" это не функция. "Unit" должен содержать сущьность с некими статами (health, movementSpeed, attackPower, attackSpeed, defence...), сущьность текущего состояния (helath, mana, stamina...), сущьность отвечающую за движение юнита и т.д..
Разница в том кто дает команды куда двигаться, в одном случае скрипт передающий импуты игрока, в другом случае скрипт патрули/цели и т.д. Это компоненты которые могут управлять любым Unit на котором они висят.
Единственная причина существования наследника в этом случае это расширения функционала Unit. Например HeroUnit : Unit который будет иметь инвентарь с предметами модифицирующие статы.