士兵部分
士兵代码
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功能教程,感谢唐老师的教程。