unity 敌人
using System.Collections; using System.Collections.Generic; using UnityEngine; public class AI : MonoBehaviour {undefined public GameObject player; public float attackrange; public float movespeed; // Start is called before the first frame update // Update is called once per frame void FixedUpdate() {undefined float dist = Vector3.Distance(player.transform.position, transform.position); if (dist > attackrange) {undefined transform.Translate(Vector3.right * movespeed * Time.deltaTime); } Vector2 direction = player.transform.position - transform.position; float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg; transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward); } } ———————————————— 版权声明:本文为CSDN博主「可没就是说」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_36190719/article/details/112884287
跟踪方式
宠物跟踪,检测到玩家离开一定范围后跟踪
玩家代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerMove : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () { float h = Input.GetAxis ("Horizontal"); float v = Input.GetAxis ("Vertical"); if(h!=0 || v!=0){ transform.LookAt (transform.position+new Vector3(h,0,v)); transform.Translate (transform.forward*Time.deltaTime*5f,Space.World); } } }
宠物移动代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PetMove : MonoBehaviour { public Transform player;//主角 public float speed=1f;//移动的阻尼,值越小,移动越平缓 // Use this for initialization void Start () { } // Update is called once per frame void Update () {//如果主角和宠物直接的距离大于5,控制宠物跟随主角移动 if(Vector3.Distance(player.position,transform.position)>5f){ PetSmothFlow (); //to do。。播放移动动画 } //to do。。播放站立动画 //控制宠物的朝向 transform.LookAt (player.position); } //控制宠物的位置平滑移动 void PetSmothFlow(){ transform.position=Vector3.Lerp (transform.position,player.position,Time.deltaTime*speed); } }
raycast射线扇形检测
// // LookDecision // //放射线检测 private bool Look(StateController controller) { var defaultStats = controller.defaultStats; //一条向前的射线 if (LookAround(controller, Quaternion.identity, Color.green)) return true; //多一个精确度就多两条对称的射线,每条射线夹角是总角度除与精度 float subAngle = (defaultStats.lookAngle / 2) / defaultStats.lookAccurate; for (int i = 0; i < defaultStats.lookAccurate; i++) { if (LookAround(controller, Quaternion.Euler(0, -1 * subAngle * (i + 1), 0), Color.green) || LookAround(controller, Quaternion.Euler(0, subAngle * (i + 1), 0), Color.green)) return true; } return false; } //射出射线检测是否有Player static public bool LookAround(StateController controller, Quaternion eulerAnger,Color DebugColor) { Debug.DrawRay(controller.eyes.position, eulerAnger * controller.eyes.forward.normalized * controller.defaultStats.lookRange, DebugColor); RaycastHit hit; if (Physics.Raycast(controller.eyes.position, eulerAnger * controller.eyes.forward, out hit, controller.defaultStats.lookRange) && hit.collider.CompareTag("Player")) { controller.chaseTarget = hit.transform; return true; } return false; }
自己的扇形检测
public class Tracking : MonoBehaviour { // // LookDecision // [Range(0, 360)] public float angle = 90f; //检测前方角度范围 [Range(0, 100)] public float distance = 25f; //检测距离 public float rotatePerSecond = 90f; //每秒旋转角度 public int LayerMask = 3; //不发生碰撞的层 bool detected = false; int LM; void Start() { LM = ~(1 << LayerMask); } // Update is called once per frame void Update() { if (GM.isActive) { if (detected) { //tracking } else { //detection Vector3 tmp = new Vector3(0, 0, -angle / 2 + Mathf.Repeat(rotatePerSecond * Time.time, angle)); Quaternion Angel = Quaternion.Euler(tmp); Vector3 tmp2 = Angel * new Vector3(0,1,0); RaycastHit2D hit = Physics2D.Raycast(transform.position, tmp2, 120f, LM); Debug.DrawRay(transform.position, tmp2, Color.red); if (hit.collider == null) { Debug.Log("Angel.y: "+Angel.y); Debug.Log("vector: " + tmp2); } else if (hit.collider.gameObject.CompareTag("Player")) { //检测到 Debug.Log("Find player"); detected = true; GM.isActive = false; } else { } } } } }
怪物巡逻
public class Enemy : MonoBehaviour { // Start is called before the first frame update public float enemy_speed = 11f; public float attack_dis = 3f; public float x1, y1, x2, y2; public int direction = 0; float t = 0.0f; public GameObject player; void Start() { } // Update is called once per frame void Update() { if (GM.isActive) { float dis = Vector2.Distance(player.transform.position, transform.position); if(dis < attack_dis) { direction = -1; transform.position = Vector2.MoveTowards(transform.position, player.transform.position,enemy_speed*Time.deltaTime); } else { if(direction == 0) { transform.position = new Vector2(Mathf.Lerp(x1, x2, t), y1); t += 0.5f * Time.deltaTime; if(t > 1.0f) { Debug.Log("direction change 0 to 1"); t = 0.0f; direction = 1; } } if (direction == 1) { transform.position = new Vector2(x2,Mathf.Lerp(y1, y2, t)); t += 0.5f * Time.deltaTime; if (t > 1.0f) { Debug.Log("direction change 1 to 2"); t = 0.0f; direction = 2; } } if (direction == 2) { transform.position = new Vector2(Mathf.Lerp(x2, x1, t), y2); t += 0.5f * Time.deltaTime; if (t > 1.0f) { Debug.Log("direction change 2 to 3"); t = 0.0f; direction = 3; } } if (direction == 3) { transform.position = new Vector2(x1, Mathf.Lerp(y2, y1, t)); t += 0.5f*Time.deltaTime; if (t > 1.0f) { t = 0.0f; direction = 0; } } } } } }
血条
public class UI : MonoBehaviour { public Text score; public GameObject gameover; public Slider HPSlider; public static int HP = 100; // Start is called before the first frame update void Start() { HPSlider.value = HPSlider.maxValue = HP; } // Update is called once per frame void Update() { score.text = "score: " + GM.score; if (HP>=0) { HPSlider.value = HP; } if (HP < 0) { GM.isActive = false; } if (!GM.isActive) { gameover.SetActive(true); } } public static void Atack(int damage) { HP -= damage; } }
血条