游戏开发中常用几种操作,控制玩家攻击以及点击鼠标控制玩家具体移动方向。接下来展示完整代码与大家一同分享。
控制玩家攻击:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum PlayerState
{
ControlWalk,
NormalAttack,
SkillAttack,
Death,
Send
}
public enum AttackState
{
//攻击时的状态
Moving,
Idle,
Attack
}
public class PlayerAttack : MonoBehaviour
{
public static PlayerAttack _instance;
public PlayerState state = PlayerState.ControlWalk;
public AttackState attack_state = AttackState.Idle;
public string aniname_normalattack;//普通攻击的动画
public string aniname_idle;
public string aniname_now;
public float time_normalattack;//普通攻击的时间
public float rate_normalattack = 1;
private float timer = 0;
public float min_distance = 5;//默认攻击的最小距离
private Transform target_normalattack;
private PlayerMove move;
public GameObject effect;
private bool showEffect=false;
private PlayerStatus ps;
public float miss_rate = 0.25f;
public GameObject hudtextPrefab;
private GameObject hudtextFollow;
public GameObject hudtextGo;
private HUDText hudtext;
public AudioClip miss_sound;
public GameObject body;
private Color normal;
public string aniname_death;
public GameObject[] efxArray;
private Dictionary<string, GameObject> efxDict = new Dictionary<string, GameObject>();
public bool isLockingTarget=false;//是否正在选择目标
private SkillInfo info=null;
//结算面板
// public UISprite uiSend;
private void Awake()
{
_instance = this;
move=this.GetComponent<PlayerMove>();
ps=this.GetComponent<PlayerStatus>();
normal=body.GetComponent<Renderer>().material.color;
hudtextFollow = transform.Find("HUDText").gameObject;
// uiSend = transform.Find("Settlement page").gameObject.GetComponent<UISprite>();
// uiSend.gameObject.SetActive(false);
foreach(GameObject go in efxArray)
{
efxDict.Add(go.name, go);
}
}
private void Start()
{
hudtextGo = NGUITools.AddChild(HUDTextParent._instance.gameObject, hudtextPrefab);
hudtext = hudtextGo.GetComponent<HUDText>();
UIFollowTarget followTarget = hudtextGo.GetComponent<UIFollowTarget>();
followTarget.target = hudtextFollow.transform;
followTarget.gameCamera = Camera.main;
}
private void Update()
{
if(state==PlayerState.Death)
{
//死亡 播放死亡特效
GetComponent<Animation>().CrossFade(aniname_death);
// uiSend.gameObject.SetActive(true);
state = PlayerState.Send;
}
if(isLockingTarget==false&&Input.GetMouseButtonDown(0)&&state!=PlayerState.Death)
{
//做射线检测
Ray ray=Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
bool isCollider=Physics.Raycast(ray, out hitInfo);
if(isCollider&&hitInfo.collider.tag==Tags.enemy)
{
//当我们点击了一个敌人的时候
target_normalattack = hitInfo.collider.transform;
state = PlayerState.NormalAttack;//进入普通攻击模式
timer = 0;
showEffect=false;
}
else
{
state = PlayerState.ControlWalk;
target_normalattack= null;
}
}
if(state==PlayerState.NormalAttack)
{
if (target_normalattack == null)
{
state = PlayerState.ControlWalk;
}
else
{
float distance = Vector3.Distance(transform.position, target_normalattack.position);
if (distance <= min_distance)
{
//进行攻击
transform.LookAt(target_normalattack.position);
attack_state = AttackState.Attack;
timer += Time.deltaTime;
GetComponent<Animation>().CrossFade(aniname_now);
if (timer >= time_normalattack)
{
aniname_now = aniname_idle;
if (showEffect == false)
{
showEffect = true;
//播放特效
GameObject.Instantiate(effect, target_normalattack.position, Quaternion.identity);
target_normalattack.GetComponent<WolfBaby>().TakeDamage(GetAttack());
}
}
if (timer >= (1f / rate_normalattack))
{
timer = 0; showEffect = false;
aniname_now = aniname_normalattack;
}
}
else
{
//走向敌人
attack_state = AttackState.Moving;
move.SimpleMove(target_normalattack.position);
}
}
}
if(isLockingTarget&&Input.GetMouseButtonDown(0))
{
OnLockTarget();
}
}
public int GetAttack()
{
return (int)(EquipmentUI._instance.attack + ps.attack + ps.attack_plus);
}
public void TakeDamage(int attack)
{
if (state == PlayerState.Death) return;
float def = EquipmentUI._instance.def + ps.def + ps.def_plus;
float temp = attack * ((200 - def) / 200);
if(temp<1)temp= 1;
float value = Random.Range(0f, 1f);
if(value<miss_rate)
{
//Miss
AudioSource.PlayClipAtPoint(miss_sound, transform.position);
hudtext.Add("Miss", Color.blue, 1);
}
else
{
hudtext.Add("-"+temp,Color.red, 1);
ps.hp_remain -= (int)temp;
StartCoroutine(ShowBodyRed());
if(ps.hp_remain<=0)
{
ps.hp_remain = 0;
state=PlayerState.Death;
}
}
HeadStatusUI._instance.UpdateShow();
}
IEnumerator ShowBodyRed()
{
body.GetComponent<Renderer>().material.color = Color.red;
yield return new WaitForSeconds(1f);
body.GetComponent<Renderer>().material.color = normal;
}
private void OnDestroy()
{
GameObject.Destroy(hudtextGo);
}
public void UseSkill(SkillInfo info)
{
if(ps.heroType==HeroType.Magician)
{
if(info.applicableRole==ApplicableRole.Swordman)
{
return;
}
}
if(ps.heroType==HeroType.Swordman)
{
if(info.applicableRole==ApplicableRole.Magician)
{
return;
}
}
switch(info.applyType)
{
case ApplyType.Passive:
StartCoroutine( OnPassiveSkillUse(info));
break;
case ApplyType.Buff:
StartCoroutine(OnBuffSkillUse(info));
break;
case ApplyType.SingleTarget:
OnSingleTargetSkillUse(info);
break;
case ApplyType.MultiTarget:
OnMultiTargetSkillUse(info);
break;
}
}
//处理增益技能
IEnumerator OnPassiveSkillUse(SkillInfo info)
{
state = PlayerState.SkillAttack;
GetComponent<Animation>().CrossFade(info.aniname);
yield return new WaitForSeconds(info.anitime);
state = PlayerState.ControlWalk;
int hp = 0, mp = 0;
if(info.applyProperty==ApplyProperty.HP)
{
hp = info.applyValue;
}
else if(info.applyProperty== ApplyProperty.MP)
{
mp = info.applyValue;
}
ps.GetDrug(hp, mp);
//实例化特效
GameObject prefab = null;
efxDict.TryGetValue(info.efx_name, out prefab);
GameObject.Instantiate(prefab, transform.position,Quaternion.identity);
}
IEnumerator OnBuffSkillUse(SkillInfo info)
{
state = PlayerState.SkillAttack;
GetComponent<Animation>().CrossFade(info.aniname);
yield return new WaitForSeconds(info.anitime);
state = PlayerState.ControlWalk;
//实例化特效
GameObject prefab= null;
efxDict.TryGetValue(info.efx_name, out prefab);
GameObject.Instantiate(prefab,transform.position, Quaternion.identity);
switch(info.applyProperty)
{
case ApplyProperty.Attack:
ps.attack *= (info.applyValue / 100f);
break;
case ApplyProperty.AttackSpeed:
rate_normalattack *= (info.applyValue / 100f);
break;
case ApplyProperty.Def:
ps.def *= (info.applyValue / 100f);
break;
case ApplyProperty.Speed:
move.speed *= (info.applyValue / 100f);
break;
}
yield return new WaitForSeconds(info.applyTime);
switch(info.applyProperty)
{
case ApplyProperty.Attack:
ps.attack /= (info.applyValue / 100f);
break;
case ApplyProperty.AttackSpeed:
rate_normalattack /= (info.applyValue / 100f);
break;
case ApplyProperty.Def:
ps.def /= (info.applyValue / 100f);
break;
case ApplyProperty.Speed:
move.speed /= (info.applyValue / 100f);
break;
}
}
//准备选择目标
void OnSingleTargetSkillUse(SkillInfo info)
{
state = PlayerState.SkillAttack;
CursorManager._instance.SetLockTarget();
isLockingTarget = true;
this.info =info;
}
//选择目标完成,开始技能的释放
void OnLockTarget()
{
isLockingTarget= false;
switch(info.applyType)
{
case ApplyType.SingleTarget:
StartCoroutine( OnLockSingleTarget());
break;
case ApplyType.MultiTarget:
StartCoroutine(OnLockMultiTarget());
break;
}
}
IEnumerator OnLockSingleTarget()
{
Ray ray=Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
bool isCollider=Physics.Raycast(ray, out hitInfo);
if(isCollider&&hitInfo.collider.tag==Tags.enemy)
{
//选择了一个敌人
GetComponent<Animation>().CrossFade(info.aniname);
yield return new WaitForSeconds(info.anitime);
state = PlayerState.ControlWalk;
//实例化特效
GameObject prefab = null;
efxDict.TryGetValue(info.efx_name, out prefab);
GameObject.Instantiate(prefab, hitInfo.collider.transform.position, Quaternion.identity);
hitInfo.collider.GetComponent<WolfBaby>().TakeDamage((int)(GetAttack() * (info.applyValue / 100f)));
}
else
{
state = PlayerState.NormalAttack;
}
CursorManager._instance.SetNormal();
}
void OnMultiTargetSkillUse(SkillInfo info)
{
state = PlayerState.SkillAttack;
CursorManager._instance.SetLockTarget();
isLockingTarget = true;
this.info=info;
}
IEnumerator OnLockMultiTarget()
{
CursorManager._instance.SetNormal();
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
bool isCollider = Physics.Raycast(ray ,out hitInfo,11);
if(isCollider)
{
GetComponent<Animation>().CrossFade(info.aniname);
yield return new WaitForSeconds(info.anitime);
state = PlayerState.ControlWalk;
//实例化特效
GameObject prefab = null;
efxDict.TryGetValue(info.efx_name,out prefab);
GameObject go=GameObject.Instantiate(prefab,hitInfo.point+Vector3.up*0.5f,Quaternion.identity);
go.GetComponent<MagicSphere>().attack = GetAttack() * (info.applyValue / 100f);
}
else
{
state = PlayerState.ControlWalk;
}
}
}
控制玩家具体移动方位:
包括实例化点击等等,适合有游戏开发基础的游戏人观看,以下代码没有仔细优化,但是大致思路如下,我很期待与你讨论更加优质的方法。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class PlayerDir : MonoBehaviour
{
public GameObject effect_click_prefab;
public Vector3 targetPosition= Vector3.zero;
//检测鼠标是否按下
private bool isMoving = false;
private PlayerMove playerMove;
private PlayerAttack attack;
void Start()
{
//设置默认位置为目标位置
targetPosition=transform.position;
playerMove=this.GetComponent<PlayerMove>();
attack=this.GetComponent<PlayerAttack>();
}
// Update is called once per frame
void Update()
{
if (attack.state == PlayerState.Death) return;
//鼠标按下
// !UICamera.isOverUI
if (attack.isLockingTarget==false&&Input.GetMouseButtonDown(0)&&UICamera.isOverUI==false)
{
Ray ray=Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
bool isCollider=Physics.Raycast(ray, out hitInfo);
if(isCollider&&hitInfo.collider.tag==Tags.ground)
{
isMoving=true;
ShowClickEffect(hitInfo.point);
LookAtTarget(hitInfo.point);
}
}
//鼠标抬起
if(Input.GetMouseButtonUp(0))
{
isMoving=false;
}
if(isMoving)
{
//得到移动位置
//让主角朝向位置
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
bool isCollider=Physics.Raycast(ray,out hitInfo);
if(isCollider&&hitInfo.collider.tag== Tags.ground)
{
LookAtTarget(hitInfo.point);
}
}
else
{
if(playerMove.isMoving)
{
//text
if (attack.state == PlayerState.Send)
targetPosition = Vector3.zero;
LookAtTarget(targetPosition);
}
}
}
/// <summary>
/// 实例化点击的效果
/// </summary>
void ShowClickEffect(Vector3 hitPoint)
{
hitPoint = new Vector3(hitPoint.x, hitPoint.y+0.2f, hitPoint.z);
GameObject.Instantiate(effect_click_prefab,hitPoint,Quaternion.identity);
}
//让主角朝向位置
void LookAtTarget(Vector3 hitPoint)
{
targetPosition= hitPoint;
targetPosition=new Vector3(targetPosition.x,transform.position.y,targetPosition.z);
this.transform.LookAt(targetPosition);
}
}
以上是我demo中这一部分的完整代码,对于demo感兴趣的小伙伴可以私聊我,了解大致过程。以上代码提供给大家学习以及思考。甚至可以直接使用在demo里面,希望大家获得更加优质的办法可以与我分享,创作不易,喜欢就点个赞支持一下吧!