Unity3D效果实现:主角篇
我们来实现RPG游戏中第三人称的主角功能实现
1.摄像机
实现效果:摄像机跟随主角转动而转动,位置处于主角身后
- 首先需要创建一个空物体,其位置和主角位置一样,随后添加一个摄像机作为其子物体,并将其挪至主角身后。
- 随后挂上该脚本
sing System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraControl : MonoBehaviour
{
private Transform player;
private Vector3 dir;
// Start is called before the first frame update
void Start()
{
player = GameObject.FindWithTag("Player").transform;
dir = player.transform.position - transform.position;
}
// Update is called once per frame
void Update()
{
transform.position = player.transform.position - dir;
//如果指针为呼出状态,则不做任何事
if (Cursor.lockState == CursorLockMode.None)
{
Debug.Log("do nothing");
return;
}
float mouseX = Input.GetAxis("Mouse X");
transform.Rotate(Vector3.up, mouseX * 90 * Time.deltaTime);
}
}
2.人物状态
- 人物包含攻击,默认,受伤,奔跑等状态,需要一个状态管理类来管理
- 人物的攻击需要使用动画和特效来完成,在动画中添加关键帧事件可以调用函数
- 人物包含默认的属性如生命值,攻击力等
- 脚本代码如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum PlayerState
{
idle,
run,
die,
attack,
}
public class PlayerControl : MonoBehaviour
{
private PlayerState state = PlayerState.idle;
private Rigidbody rbody;
private Animator animator;
public int MaxHp = 100;
public int hp = 100;
//特效数组
private List<Transform> fxList;
// Start is called before the first frame update
void Start()
{
animator = GetComponent<Animator>();
rbody = GetComponent<Rigidbody>();
Cursor.lockState = CursorLockMode.Locked;
fxList = new List<Transform>();
}
// Update is called once per frame
void Update()
{
//主角与摄像机同步旋转
switch(state)
{
case PlayerState.idle:
Rotate();
Move();
Attack();
animator.SetBool("Run", false);
break;
case PlayerState.run:
Rotate();
Move();
Attack();
animator.SetBool("Run", true);
break;
case PlayerState.die:
break;
case PlayerState.attack:
break;
}
if(Input.GetKeyDown(KeyCode.LeftAlt))
{
Cursor.lockState = Cursor.lockState == CursorLockMode.Locked ? CursorLockMode.None : CursorLockMode.Locked;
}
if(Cursor.lockState==CursorLockMode.None)
{
return;
}
//要删除的特效
Transform fx = null;
foreach(Transform trans in fxList)
{
//特效移动
trans.Translate(Vector3.forward * 20 * Time.deltaTime);
Collider[] colliders = Physics.OverlapSphere(transform.position, 1f);
foreach(Collider collider in colliders)
{
if(collider.tag=="Enemy")
{
collider.GetComponent<EnemyControl>().GetDamage(20);
//待删除的火焰特效
fx = trans;
//爆炸特效
//加载特效预制件
GameObject fxPre = Resources.Load<GameObject>("Explosion");
//实例化特效
GameObject go = Instantiate(fxPre, collider.transform.position, collider.transform.rotation);
Destroy(go, 2f);
break;
}
}
}
if(fx!=null)
{
fxList.Remove(fx);
}
}
public void Rotate()
{
transform.rotation = Camera.main.transform.parent.rotation;
}
void Move()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector3 dir = new Vector3(horizontal, 0, vertical);
if (dir != Vector3.zero)
{
rbody.velocity = transform.forward * vertical * 4;
rbody.velocity += transform.right * horizontal * 2;
state = PlayerState.run;
}
else
{
state = PlayerState.idle;
}
}
void Attack()
{
if(Input.GetKeyDown(KeyCode.Q))
{
animator.SetTrigger("Attack");
state = PlayerState.attack;
}
}
void AttackEnd()
{
state = PlayerState.idle;
}
public void GetDamage(int damage)
{
hp -= damage;
if(hp<0)
{
state = PlayerState.die;
animator.SetTrigger("Die");
}
}
public void Revive(Vector3 position)
{
if(state==PlayerState.die)
{
animator.SetTrigger("Revive");
state = PlayerState.idle;
transform.position = position;
}
}
void Damage(int damage)
{
Collider[] colliders = Physics.OverlapSphere(transform.position, 3f);
foreach (Collider collider in colliders)
{
//判定是敌人并在60度的攻击范围内
if (collider.tag == "Enemy" && Vector3.Angle(collider.transform.
position - transform.position, transform.forward)<60)
{
collider.GetComponent<EnemyControl>().GetDamage(damage);
}
}
}
Transform FX(string name,float desTime)
{
GameObject fxPre = Resources.Load<GameObject>(name);
//实例化特效
GameObject go = Instantiate(fxPre, transform.position, transform.rotation);
//删除特效物体
Destroy(go, desTime);
return go.transform;
}
void Attack1_1()
{
Damage(20);
FX("fx_hr_authur_attack_01_1", 0.5f);
}
void ClearFXList()
{
fxList.Clear();
}
}