U3D游戏开发控制玩家攻击以及移动方向控制系列

游戏开发中常用几种操作,控制玩家攻击以及点击鼠标控制玩家具体移动方向。接下来展示完整代码与大家一同分享。

控制玩家攻击:

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里面,希望大家获得更加优质的办法可以与我分享,创作不易,喜欢就点个赞支持一下吧!

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nicole Potter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值