15、子弹开火的逻辑
在Player.cs中添加
public class Player : NetworkBehaviour
{
……
private float nextFire; //下一次开火的时间
public float fireRate = 0.75f; //两次开火至少相隔的时间
public Transform shotPos; // 开火位置
……
private void FixedUpdate()
{
……
//开火
if (Input.GetButton("Fire1"))
{
if (Time.time > nextFire)
{
nextFire = Time.time + fireRate;
CmdShoot((short) (shotPos.position.x * 10), (short) (shotPos.position.z * 10));
}
}
}
……
[Command]
void CmdShoot(short xPos, short zPos)
{
Vector3 shotCenter =
Vector3.Lerp(shotPos.position, new Vector3(xPos / 10f, shotPos.position.y, zPos / 10f), 0.6f);
// 创建子弹,并同步到客户端
// 所有客户端进行特效显示
}
[ClientRpc]
protected void RpcOnShot()
{
// 显示特效
}
}
16、子弹开火位置的设置
在炮台下建立子对象,开火位置ShotPos,放置炮台口
![](https://img-blog.csdnimg.cn/de629c49afd14410bd77e1fac3a2d1a3.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAfkxvbWlzc34=,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/d2b24bf3974445b5aa0eb0d28c37db72.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAfkxvbWlzc34=,size_18,color_FFFFFF,t_70,g_se,x_16)
17、场景中子弹生成
![](https://img-blog.csdnimg.cn/369f5e704ac8492daec695dc16916a66.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAfkxvbWlzc34=,size_20,color_FFFFFF,t_70,g_se,x_16)
新建一个3D球形,让子弹成为它的子对象,命名为Bullet,并删除Mesh Renderer,在3D球形上添加刚体实现碰撞机制,然后添加网络ID和位置同步的组件。
![](https://img-blog.csdnimg.cn/6cfb026aa9cb432abf3fee94a8c8e309.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAfkxvbWlzc34=,size_20,color_FFFFFF,t_70,g_se,x_16)
新建Bullet.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;
public class Bullet : NetworkBehaviour
{
public float speed = 15;
private Rigidbody myRigidbody;
private void Awake()
{
myRigidbody = GetComponent<Rigidbody>();
}
private void Start()
{
myRigidbody.velocity = speed * transform.forward;
}
}
将
Bullet.cs添加到Bullet对象上
![](https://img-blog.csdnimg.cn/2d7756c8f72e422c81f9333e3f24ea76.png)
保存成预制体,并在场景中删除
![](https://img-blog.csdnimg.cn/78997857747a40199b0b99899a9fe6d3.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAfkxvbWlzc34=,size_12,color_FFFFFF,t_70,g_se,x_16)
在Player.cs继续完善子弹发射逻辑
public class Player : NetworkBehaviour
{
……
public GameObject BulletPrefab; //
……
……
……
[Command]
void CmdShoot(short xPos, short zPos)
{
Vector3 shotCenter =
Vector3.Lerp(shotPos.position, new Vector3(xPos / 10f, shotPos.position.y, zPos / 10f), 0.6f);
// 创建子弹,并同步到客户端
GameObject obj = Instantiate(BulletPrefab, shotCenter, Quaternion.Euler(0, turret.eulerAngles.y, 0)); //把预制体实例化出子弹
NetworkServer.Spawn(obj,obj.GetComponent<NetworkIdentity>().assetId); // 在服务器端生成,并同步
// 所有客户端进行特效显示
RpcOnShot();
}
[ClientRpc]
protected void RpcOnShot()
{
// 显示特效
}
}
![](https://img-blog.csdnimg.cn/8272b15983b241bd8788068dcde8ecf1.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAfkxvbWlzc34=,size_20,color_FFFFFF,t_70,g_se,x_16)
由于预制体子弹会在服务器中生成,所以需要提前注册
![](https://img-blog.csdnimg.cn/4b5c80af1157401b80761e7ee7061fca.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAfkxvbWlzc34=,size_18,color_FFFFFF,t_70,g_se,x_16)
测试
![](https://img-blog.csdnimg.cn/1edac920be584089bfd0d498549e3ed8.gif)