Паттерн Стратегия в 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 шт):

Автор решения: Yaroslav

У вас сломанная архитектура классов. Классов Player и Enemy не должно быть, потому что они у вас не отличаются.

Есть сущность "Human", который я бы назвал "Unit", поскольку под ней может быть и гоблин и черт лысый по желанию, "Human" это не функция. "Unit" должен содержать сущьность с некими статами (health, movementSpeed, attackPower, attackSpeed, defence...), сущьность текущего состояния (helath, mana, stamina...), сущьность отвечающую за движение юнита и т.д..

Разница в том кто дает команды куда двигаться, в одном случае скрипт передающий импуты игрока, в другом случае скрипт патрули/цели и т.д. Это компоненты которые могут управлять любым Unit на котором они висят.

Единственная причина существования наследника в этом случае это расширения функционала Unit. Например HeroUnit : Unit который будет иметь инвентарь с предметами модифицирующие статы.

→ Ссылка