1:添加unity自带的第一人称角色控制器,命名为hreo
2:添加第三人称角色控制器。这里是添加源文件Sources下面的。如箭头指示:而不是“3rd Person Controller”。并命名为NPC。并设置预设,和加上BOX碰撞器。产生多个NPC。结构图:
3:修改hreo自带的Mouse Look脚本
1 using UnityEngine; 2 using System.Collections; 3 4 /// MouseLook rotates the transform based on the mouse delta. 5 /// Minimum and Maximum values can be used to constrain the possible rotation 6 7 /// To make an FPS style character: 8 /// - Create a capsule. 9 /// - Add the MouseLook script to the capsule. 10 /// -> Set the mouse look to use LookX. (You want to only turn character but not tilt it) 11 /// - Add FPSInputController script to the capsule 12 /// -> A CharacterMotor and a CharacterController component will be automatically added. 13 14 /// - Create a camera. Make the camera a child of the capsule. Reset it's transform. 15 /// - Add a MouseLook script to the camera. 16 /// -> Set the mouse look to use LookY. (You want the camera to tilt up and down like a head. The character already turns.) 17 [AddComponentMenu("Camera-Control/Mouse Look")] 18 public class MouseLook : MonoBehaviour { 19 20 public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 } 21 public RotationAxes axes = RotationAxes.MouseXAndY; 22 public float sensitivityX = 15F; 23 public float sensitivityY = 15F; 24 25 public float minimumX = -360F; 26 public float maximumX = 360F; 27 28 public float minimumY = -60F; 29 public float maximumY = 60F; 30 31 float rotationY = 0F; 32 33 //鼠标准心 34 public Texture2D tex_fire; 35 36 void Update () 37 { 38 if (axes == RotationAxes.MouseXAndY) 39 { 40 //float rotationX = transform.localEulerAngles.y + Input.GetAxis("Mouse X") * sensitivityX; 41 42 //rotationY += Input.GetAxis("Mouse Y") * sensitivityY; 43 //rotationY = Mathf.Clamp (rotationY, minimumY, maximumY); 44 45 //transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0); 46 } 47 else if (axes == RotationAxes.MouseX) 48 { 49 transform.Rotate(0, Input.GetAxis("Mouse X") , 0); 50 } 51 else 52 { 53 //rotationY += Input.GetAxis("Mouse Y") * sensitivityY; 54 //rotationY = Mathf.Clamp (rotationY, minimumY, maximumY); 55 56 transform.localEulerAngles = new Vector3(-rotationY, transform.localEulerAngles.y, 0); 57 } 58 } 59 60 void OnGUI() 61 { 62 if (tex_fire) 63 { 64 //绘制鼠标准心 65 float x = Input.mousePosition.x - tex_fire.width / 2; 66 float y = Screen.height - Input.mousePosition.y - tex_fire.height / 2; 67 68 GUI.DrawTexture(new Rect(x, y, tex_fire.width, tex_fire.height), tex_fire); 69 } 70 } 71 72 void Start () 73 { 74 // Make the rigid body not change rotation 75 if (GetComponent<Rigidbody>()) 76 GetComponent<Rigidbody>().freezeRotation = true; 77 78 //取消鼠标默认状态 79 Screen.showCursor = false; 80 } 81 }
5 :编写脚本命名为dr.cs绑定到NPC上
1 using UnityEngine; 2 using System.Collections; 3 4 public class dr : MonoBehaviour 5 { 6 7 //是否绘制敌人血条 8 bool showBlood = false; 9 //血条资源贴图 10 public Texture2D tex_red; 11 public Texture2D tex_black; 12 //生命值 13 private int HP = 100; 14 //主角对象 15 private GameObject hero; 16 // Use this for initialization 17 void Start() 18 { 19 hero = GameObject.Find("Hero"); 20 } 21 22 // Update is called once per frame 23 void Update() 24 { 25 //设置始终朝向 26 transform.LookAt(hero.transform); 27 } 28 29 void OnGUI() 30 { 31 if (showBlood) 32 { 33 //绘制敌人血条 34 int blood_widht = tex_red.width * HP / 100; 35 GUI.DrawTexture(new Rect(5, 5, tex_black.width, tex_black.height), tex_black); 36 GUI.DrawTexture(new Rect(5, 5, blood_widht, tex_red.height), tex_red); 37 } 38 } 39 40 /// <summary> 41 /// 当鼠标在GUIElement(GUI元素)或Collider(碰撞体)上点击时调用OnMouseDown。 42 /// </summary> 43 void OnMouseDown() 44 { 45 //敌人击中目标 46 if (HP > 0) 47 { 48 //减血 49 HP -= 5; 50 //击打回馈 51 } 52 } 53 /// <summary> 54 /// 当用户释放鼠标按钮时调用OnMouseUp。 55 /// </summary> 56 void OnMouseUp() 57 { 58 //击打敌人后移动一段距离 59 transform.Translate(Vector3.back * 0.1f); 60 } 61 /// <summary> 62 /// 当鼠标悬浮在GUIElement(GUI元素)或Collider(碰撞体)上时调用 OnMouseOver 。 63 /// </summary> 64 void OnMouseOver() 65 { 66 //当对着敌人时,开始绘制血条,即显示敌人当前的血条 67 showBlood = true; 68 69 } 70 /// <summary> 71 /// 当Collider(碰撞体)停止触发trigger(触发器)时调用OnTriggerExit。 72 /// </summary> 73 void OnMouseExit() 74 { 75 //结束绘制血条 76 showBlood = false; 77 } 78 }
7:dr.cs脚本实现了。当鼠标指向敌人时,显示敌人当前的血条情况,
当击中敌人时候。敌人会后退几步。
dr.cs脚本升级:敌人AI即人工智能
实现功能:让NPC有自己的生命周期:就是自己巡逻。当在巡逻范围内看到hero,即跑向hero开始攻击(这里暂为实现)
1 using UnityEngine; 2 using System.Collections; 3 4 public class drAI : MonoBehaviour 5 { 6 7 //敌人状态 8 9 10 //敌人站立状态 11 public const int STATE_STAND = 0; 12 //敌人行走状态 13 public const int STATE_WALK = 1; 14 //敌人奔跑状态 15 public const int STATE_RUN = 2; 16 //记录敌人的当前状态 17 private int enemyState; 18 //主角对象 19 private GameObject hero; 20 //备份上一次的敌人思考时间 21 private float backUptime; 22 //敌人思考下一次行为的时间 23 public const int AI_THINK_TIME = 2; 24 //敌人的巡逻范围 25 public const int AI_ATTACK_DISTANCE = 10; 26 27 28 // Use this for initialization 29 void Start() 30 { 31 //得到主角对象 32 hero = GameObject.Find("/Hero"); 33 //设置敌人的默认状态为站立 34 enemyState = STATE_WALK; 35 } 36 37 // Update is called once per frame 38 void Update() 39 { 40 //判断敌人与主角的距离 当在巡逻范围内 41 if (Vector3.Distance(transform.position, hero.transform.position) < AI_ATTACK_DISTANCE) 42 { 43 //敌人进入奔跑状态 44 gameObject.animation.Play("run"); 45 enemyState = STATE_RUN; 46 //设置敌人面朝主角方向 47 transform.LookAt(hero.transform); 48 } 49 //敌人进入巡逻状态 50 else 51 { 52 //计算敌人的思考时间 53 if (Time.time - backUptime >= AI_THINK_TIME) 54 { 55 //敌人开始思考 56 backUptime = Time.time; 57 //取得0~2之间的随机数 58 int rand = Random.Range(0, 2); 59 if (rand == 0) 60 { 61 //敌人进入站立状态 62 gameObject.animation.Play("idle"); 63 enemyState = STATE_STAND; 64 } 65 else if (rand == 1) 66 { 67 //敌人进入行走状态 68 //敌人随机旋转角度 69 Quaternion rotate = Quaternion.Euler(0, Random.Range(1, 5) * 90, 0); 70 //1秒内完成敌人旋转 71 transform.rotation = Quaternion.Slerp(transform.rotation, rotate, Time.deltaTime * 1000); 72 //播放行走动画 73 gameObject.animation.Play("walk"); 74 enemyState = STATE_WALK; 75 } 76 } 77 } 78 switch (enemyState) 79 { 80 case STATE_STAND: break; 81 case STATE_WALK: 82 //敌人行走 83 transform.Translate(Vector3.forward * Time.deltaTime); 84 break; 85 case STATE_RUN: 86 //敌人朝向主角奔跑 87 if (Vector3.Distance(transform.position, hero.transform.position) > 3) 88 { 89 transform.Translate(Vector3.forward * Time.deltaTime * 3); 90 } 91 break; 92 default: 93 break; 94 } 95 } 96 }
知识点:
Quaternion四元素表示旋转。Quaternion.Euler()方法返回一个旋转的四元素。该方法参数表示旋转的三维角度。执行该方法后,将
四元素赋值给一个对象的旋转变量
transform.rotation = rotate
即可在一帧内完成旋转,若想在一段时间内完成旋转,就需要用到
Quaternion.Slerp()方法:
第一个参数表示模型旋转的起始角度
第二参数表示模型的结束角度
第三个参数表示旋转消耗的时间