unity实现RTS游戏 阵型选择 士兵移动 功能

士兵部分

士兵代码

using UnityEngine;
using UnityEngine.AI;

public class Soldier : MonoBehaviour
{
    private GameObject footEffect;
    private NavMeshAgent nav;
    private Animator animator;

    private void Start()
    {
        footEffect = transform.Find("FootEffect").gameObject;
        nav = GetComponent<NavMeshAgent>();
        animator = GetComponentInChildren<Animator>();
    }    

    private void Update()
    {
        animator.SetBool("move",nav.velocity.magitude > 0);
    }

    public void MoveTo(Vector3 pos)
    {
       nav.destination = pos; 
    }

    public void SetVisible(bool active = true)
    {
        footEffect.SetActive(active);
    }
}

士兵截图

 控制器部分(核心)

控制器代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Controller : MonoBehaviour
{
    private List<Soldier> soldierObjs = new List<Soldier>();
    private LineRenderer line;
    private RenderCamera rc;

    private Vector3 leftUpPoint;
    private Vector3 leftDownPoint;
    private Vector3 rightUpPoint;
    private Vector3 rightDownPoint;
    private Vector3 beginWorldPos;
    private Vector3 frontPos;
    private bool isMouseDown;
    private float soldierOffset = 3;

    private void Start()
    {
        line = GetComponent<LineRenderer>();
        rc = FindObjectOfType<RenderCamera>();
    }

    private void Update()
    {
        SelectSoldiers();
        RenderSoldierHead();
        ControlSoldiersMove();
    }

    private void RenderSoldierHead()
    {
        if (soldierObjs.Count > 0)
            rc.SetRenderSoldier(soldierObjs[0]);
    }

    /// <summary>
    /// 选择士兵
    /// </summary>
    private void SelectSoldiers()
    {
        if (Input.GetMouseButtonDown(0))
        {
            isMouseDown = true;
            leftUpPoint = Input.mousePosition;

            if(Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition),out RaycastHit hitInfo, 1000, 1 << LayerMask.NameToLayer("Floor")))
            {
                beginWorldPos = hitInfo.point;
            }
        }else if (Input.GetMouseButtonUp(0))
        {
            isMouseDown = false;
            line.positionCount = 0;

            for(int i = 0;i < soldierObjs.Count; i++)
            {
                soldierObjs[i].SetFootEffectVisible(false);
            }

            soldierObjs.Clear();

            if(Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition),out RaycastHit hitInfo, 1000, 1 << LayerMask.NameToLayer("Floor")))
            {
                Vector3 center = new Vector3((hitInfo.point.x + beginWorldPos.x) / 2, 1, (hitInfo.point.z + beginWorldPos.z) / 2);
                Vector3 halfExtents = new Vector3(Mathf.Abs(hitInfo.point.x - beginWorldPos.x) / 2, 1, Mathf.Abs(hitInfo.point.z - beginWorldPos.z));
                Collider[] cols = Physics.OverlapBox(center, halfExtents);
                for(int i = 0;i < cols.Length && soldierObjs.Count < 12; i++)
                {
                    Soldier soldier = cols[i].GetComponent<Soldier>();
                    if (soldier)
                    {
                        soldier.SetFootEffectVisible(true);
                        soldierObjs.Add(soldier);
                    }
                }

                soldierObjs.Sort((a, b) => 
                
                {
                    if (a.type < b.type)
                        return -1;
                    else if (a.type == b.type)
                        return 0;
                    else
                        return 1;
                });
            }
        }

        if (isMouseDown)
        {
            leftUpPoint.z = 5;

            rightDownPoint = Input.mousePosition;
            rightDownPoint.z = 5;

            leftDownPoint.y = rightDownPoint.y;
            leftDownPoint.x = leftUpPoint.x;
            leftDownPoint.z = 5;

            rightUpPoint.x = rightDownPoint.x;
            rightUpPoint.y = leftUpPoint.y;
            rightUpPoint.z = 5;

            line.positionCount = 4;
            line.SetPosition(0, Camera.main.ScreenToWorldPoint(leftUpPoint));
            line.SetPosition(1, Camera.main.ScreenToWorldPoint(rightUpPoint));
            line.SetPosition(2, Camera.main.ScreenToWorldPoint(rightDownPoint));
            line.SetPosition(3, Camera.main.ScreenToWorldPoint(leftDownPoint));
        }
    }

    /// <summary>
    /// 控制士兵移动
    /// </summary>
    private void ControlSoldiersMove()
    {
        if (Input.GetMouseButtonDown(1))
        {
            if (soldierObjs.Count == 0)
                return;

            if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition),out RaycastHit hitInfo, 1000, 1 << LayerMask.NameToLayer("Floor")))
            {
                if(Vector3.Angle((hitInfo.point - soldierObjs[0].transform.position).normalized,soldierObjs[0].transform.forward) > 60)
                {
                    soldierObjs.Sort((a,b)=>                    
                    {
                        if (a.type < b.type)
                            return -1;
                        else if (a.type == b.type)
                            if (Vector3.Distance(a.transform.position, hitInfo.point) <= Vector3.Distance(b.transform.position, hitInfo.point))
                                return -1;
                            else
                                return 1;
                        else
                            return 1;
                    });
                }

                List<Vector3> targetsPos = GetTargetPos(hitInfo.point);
                for(int i = 0; i < soldierObjs.Count; i++)
                {
                    soldierObjs[i].MoveTo(targetsPos[i]);
                }
            }
        }
    }

    private List<Vector3> GetTargetPos(Vector3 targetPos)
    {
        Vector3 nowForward = Vector3.zero;//面朝向
        Vector3 nowRight = Vector3.zero;//右朝向

        if (frontPos != Vector3.zero)
        {
            nowForward = (targetPos - frontPos).normalized;
        }
        else
        {
            nowForward = (targetPos - soldierObjs[0].transform.position).normalized;
        }

        nowRight = Quaternion.Euler(0, 90, 0) * nowForward;

        List<Vector3> targetsPos = new List<Vector3>();

        switch (soldierObjs.Count)
        {
            case 1:
                targetsPos.Add(targetPos);
                break;
            case 2:
                targetsPos.Add(targetPos + nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos - nowRight * soldierOffset / 2);
                break;
            case 3:
                targetsPos.Add(targetPos);
                targetsPos.Add(targetPos + nowRight * soldierOffset);
                targetsPos.Add(targetPos - nowRight * soldierOffset);
                break;
            case 4:
                targetsPos.Add(targetPos + nowRight * soldierOffset / 2 + nowForward * soldierOffset / 2);
                targetsPos.Add(targetPos - nowRight * soldierOffset / 2 + nowForward * soldierOffset / 2);
                targetsPos.Add(targetPos + nowRight * soldierOffset / 2 - nowForward * soldierOffset / 2);
                targetsPos.Add(targetPos - nowRight * soldierOffset / 2 - nowForward * soldierOffset / 2);
                break;
            case 5:
                targetsPos.Add(targetPos + nowForward * soldierOffset / 2);
                targetsPos.Add(targetPos + nowForward * soldierOffset / 2 - nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos + nowForward * soldierOffset / 2 + nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos - nowForward * soldierOffset / 2 - nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos - nowForward * soldierOffset / 2 + nowRight * soldierOffset / 2);
                break;
            case 6:
                targetsPos.Add(targetPos + nowForward * soldierOffset / 2);
                targetsPos.Add(targetPos - nowForward * soldierOffset / 2);
                targetsPos.Add(targetPos + nowForward * soldierOffset / 2 + nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos - nowForward * soldierOffset / 2 + nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos + nowForward * soldierOffset / 2 - nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos - nowForward * soldierOffset / 2 - nowRight * soldierOffset / 2);
                break;
            case 7:
                targetsPos.Add(targetPos + nowForward * soldierOffset);
                targetsPos.Add(targetPos + nowForward * soldierOffset - nowRight * soldierOffset);
                targetsPos.Add(targetPos + nowForward * soldierOffset + nowRight * soldierOffset);
                targetsPos.Add(targetPos - nowRight * soldierOffset);
                targetsPos.Add(targetPos + nowRight * soldierOffset);
                targetsPos.Add(targetPos);
                targetsPos.Add(targetPos - nowForward * soldierOffset);
                break;
            case 8:
                targetsPos.Add(targetPos + nowForward * soldierOffset);
                targetsPos.Add(targetPos + nowForward * soldierOffset - nowRight * soldierOffset);
                targetsPos.Add(targetPos + nowForward * soldierOffset + nowRight * soldierOffset);
                targetsPos.Add(targetPos - nowRight * soldierOffset);
                targetsPos.Add(targetPos + nowRight * soldierOffset);
                targetsPos.Add(targetPos);
                targetsPos.Add(targetPos - nowForward * soldierOffset - nowRight * soldierOffset);
                targetsPos.Add(targetPos - nowForward * soldierOffset + nowRight * soldierOffset);
                break;
            case 9:
                targetsPos.Add(targetPos + nowForward * soldierOffset);
                targetsPos.Add(targetPos + nowForward * soldierOffset - nowRight * soldierOffset);
                targetsPos.Add(targetPos + nowForward * soldierOffset + nowRight * soldierOffset);
                targetsPos.Add(targetPos - nowRight * soldierOffset);
                targetsPos.Add(targetPos + nowRight * soldierOffset);
                targetsPos.Add(targetPos);
                targetsPos.Add(targetPos - nowForward * soldierOffset - nowRight * soldierOffset);
                targetsPos.Add(targetPos - nowForward * soldierOffset + nowRight * soldierOffset);
                targetsPos.Add(targetPos - nowForward * soldierOffset);
                break;
            case 10:
                targetsPos.Add(targetPos + nowForward * soldierOffset - nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos + nowForward * soldierOffset + nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos + nowForward * soldierOffset - nowRight * soldierOffset * 1.5f);
                targetsPos.Add(targetPos + nowForward * soldierOffset + nowRight * soldierOffset * 1.5f);
                targetsPos.Add(targetPos - nowRight * soldierOffset * 1.5f);
                targetsPos.Add(targetPos + nowRight * soldierOffset * 1.5f);
                targetsPos.Add(targetPos - nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos + nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos - nowForward * soldierOffset - nowRight * soldierOffset * 1.5f);
                targetsPos.Add(targetPos - nowForward * soldierOffset + nowRight * soldierOffset * 1.5f);
                break;
            case 11:
                targetsPos.Add(targetPos + nowForward * soldierOffset - nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos + nowForward * soldierOffset + nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos + nowForward * soldierOffset - nowRight * soldierOffset * 1.5f);
                targetsPos.Add(targetPos + nowForward * soldierOffset + nowRight * soldierOffset * 1.5f);
                targetsPos.Add(targetPos - nowRight * soldierOffset * 1.5f);
                targetsPos.Add(targetPos + nowRight * soldierOffset * 1.5f);
                targetsPos.Add(targetPos - nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos + nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos - nowForward * soldierOffset - nowRight * soldierOffset * 1.5f);
                targetsPos.Add(targetPos - nowForward * soldierOffset + nowRight * soldierOffset * 1.5f);
                targetsPos.Add(targetPos - nowForward * soldierOffset);
                break;
            case 12:
                targetsPos.Add(targetPos + nowForward * soldierOffset - nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos + nowForward * soldierOffset + nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos + nowForward * soldierOffset - nowRight * soldierOffset * 1.5f);
                targetsPos.Add(targetPos + nowForward * soldierOffset + nowRight * soldierOffset * 1.5f);
                targetsPos.Add(targetPos - nowRight * soldierOffset * 1.5f);
                targetsPos.Add(targetPos + nowRight * soldierOffset * 1.5f);
                targetsPos.Add(targetPos - nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos + nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos - nowForward * soldierOffset - nowRight * soldierOffset * 1.5f);
                targetsPos.Add(targetPos - nowForward * soldierOffset + nowRight * soldierOffset * 1.5f);
                targetsPos.Add(targetPos - nowForward * soldierOffset - nowRight * soldierOffset / 2);
                targetsPos.Add(targetPos - nowForward * soldierOffset + nowRight * soldierOffset / 2);
                break;              
        }

        frontPos = targetPos;
        return targetsPos;
    }
}

绿框效果图

最多选中12位单位

阵型图示 

特别声明:本文章引用了唐老师的一些资源,如有侵权,请告知我,我立刻删除。 

本人是看的唐老师的rts功能教程,感谢唐老师的教程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值