UNet系统初次使用——联网Boxing游戏(3)

本文详细介绍了在Unity使用UNet系统实现Boxing游戏中的player移动和血量功能。通过挂载Character Controller和编写PlayerMovement脚本,实现了本地玩家的移动和旋转,并利用NetworkIdentity和NetworkTransform进行同步。此外,还创建PlayerHealth脚本,通过NetworkBehaviour同步血量,确保只有服务器能修改血量,并动态绑定血条显示。
摘要由CSDN通过智能技术生成

UNet系统初次使用——联网Boxing游戏(1)
UNet系统初次使用——联网Boxing游戏(2)
从这篇开始,便详细介绍player的实现。
player组件的uml图如下
这里写图片描述
我们便来依次讲解如何实现。
操作规则
- W —— 前进
- S —— 后退
- A —— 左移
- D —— 右移
- 鼠标左键 —— 左拳
- 鼠标邮件 —— 右拳
- 空格 —— 防御
- 鼠标移动 —— 视角转动

五、player移动 (PlayerMovement)

(1)
首先给player挂载Character Controller
这里写图片描述
然后新建一个PlayerMovement的C#代码,将其挂载到player上。
PlayerMovement主要解决的是前后左右移动和视角转动的功能。
(2)
两个变量记录移动速度和旋转速度。

    public float moveSpeed;
    public float mouseTurnSpeed;

引用挂载的CharcterController组件

    private CharacterController characterController;
    void Start () {
        characterController = GetComponent<CharacterController>();
    }

两个属性MoveDirection和RotationAmount

    public Vector3 MoveDirection
    {
        get
        {
            if (!isLocalPlayer)
            {
                return syncDirection;
            }
            float h = Input.GetAxis("Horizontal");
            float v = Input.GetAxis("Vertical");

            Vector3 direction = Mathf.Abs(v) >= Mathf.Abs(h) ? transform.forward * v : transform.right * h;
            CmdSetDirection(direction);
            return direction;
        }
    }

    public float RotationAmount
    {
        get
        {
            float rotationAmount = Input.GetAxis("Mouse X");
            return rotationAmount;
        }
    }

然后在Fixedupdate中实现移动和转向。使用isLocalPlayer确保只有本地player可以被操控。

   private void FixedUpdate()
    {
        if (!isLocalPlayer)
        {
            return;
        }
        Move(MoveDirection);
        Turn(RotationAmount);
    }

    void Move(Vector3 direction)
    {
        characterController.Move(direction * moveSpeed * Time.deltaTime);
    }

    void Turn(float rotationAmount)
    {
        transform.Rotate(transform.up, rotationAmount * mouseTurnSpeed * Time.deltaTime);
    }

这样我们基本实现了人物在本地的移动和旋转。但是如何到同步到服务器和其他的客户端呢。
(3)
为了解决这个问题,我们给Player挂载上NetworkIdentity,NetworkTransform这两个组件, 并且修改PlayerMovement,让其继承NetworkBehaviour类。

public class PlayerMovement : NetworkBehaviour

当你想挂载继承了NetworkBehavier类的代码,NetworkIdentity是必须的。
然后NetworkTransform可以不断同步人物的Transform给服务器,然后由服务器同步给各个客户端,于是就可以使得其他客户端的人物跟本地一样移动和旋转了。

但是我们移动的时候,前后左右需要有不同的动画。所以我们用一个同步变量来记录我们的方向,并且同步给服务器和各个客户端。

    [SyncVar]
    private Vector3 syncDirection;

    [Command]
    private void CmdSetDirection(Vector3 direction)
    {
        syncDirection = direction;
    }

这样基本实现了人物的移动。

六、player血量

首先我们构建两个血条,分别是player和敌人的血条。
这里写图片描述

这里写图片描述
完成之后给两个Slider分别加上LocalPlayerHP和OnlinePlayerHP两个tag。
因为player是动态加载的,所以需要通过tag来动态绑定属于自己的血条。
(1)
我们新建个PlayerHealth的代码,挂载到player上。
修改PlayerHealth继承NetworkBehaviour。

maxHealthy记录最大血量
同步变量healthy记录并同步当前血量

    public float maxHealthy;


    [SyncVar (hook = "HealthyChange")]
    public float healthy;

在服务器修改当前血量,然后同步给各个客户端。当某个人物被打倒的时候,实际上在两个客户端和服务器上都达到了,如果三个地方的人物都扣血,那么实际上总共扣了3次,这是不合理的。所以我们规定只有在服务器才能修改血量。

    public void TakeDamage(float damageAmount)
    {
        if (!isServer)
        {
            return;
        }
        healthy -= damageAmount;
    }

    private void HealthyChange(float healthy)
    {
        this.healthy = healthy;
        HpSlider.value = healthy;
        if (isLocalPlayer && healthy <= 30)
        {
            blood.gameObject.SetActive(true);
        }
    }

根据isLocalPlayer绑定相应的血条。


    private Slider HpSlider;
    private void BindHPSlider()
    {
        if (isLocalPlayer)
        {
            HpSlider = GameObject.FindWithTag("LocPlayerHP").GetComponent<Slider>();
        }
        else
        {
            HpSlider = GameObject.FindWithTag("OnlinePlayerHP").GetComponent<Slider>();
        }
    }

添加低血量特效

    public Image bloodPrefab;
    private Image blood;
    private void InstanceBlood()
    {
        if (!isLocalPlayer)
        {
            return;
        }
        blood = Instantiate(bloodPrefab);
        blood.transform.parent = GameObject.FindWithTag("Canvas").transform;
        blood.rectTransform.offsetMax = Vector2.zero;
        blood.rectTransform.offsetMin = Vector2.zero;
        blood.gameObject.SetActive(false);
        blood.transform.SetAsFirstSibling();
    }

在start中绑定Slider和低血量特效


    public void Start()
    {
        BindHPSlider();
        if (HpSlider == null)
        {
            Debug.Log("Canvas Load Fail");
        }
        InstanceBlood();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值