三、飞行和射击

目录

1.飞行的实现

2.限制玩家视角

3.射击的实现

4.附录


1.飞行的实现

(1)在Player预制体上挂载Configuration Joint组件,并修改其Y Drive属性

三、飞行和射击_第1张图片三、飞行和射击_第2张图片

(2) 修改PlayerInput.cs和PlayerController.cs以实现飞行

  • PlayerInput.cs

添加以下属性 

[SerializeField] 
private float thrusterForce = 20f;
[SerializeField] 
private ConfigurableJoint joint

 在其Start方法中添加以下语句

joint = GetComponent();

在其Update方法中添加以下语句 

Vector3 force = Vector3.zero;
if (Input.GetButton("Jump"))
{
    force = Vector3.up * thrusterForce;
    joint.yDrive = new JointDrive
    {
        positionSpring = 0f,
        positionDamper = 0f,
        maximumForce = 0f,
    };
}
else
{
    joint.yDrive = new JointDrive
    {
        positionSpring = 20f,
        positionDamper = 0f,
        maximumForce = 40f,
        };
    }
playerControllor.Thrust(force);
  • PlayerController.cs

添加以下属性 

private Vector3 thrusterForce = Vector3.zero;//向上的推力

 添加以下方法

public void Thrust(Vector3 _thrusterForce)
{
    thrusterForce = _thrusterForce;
}

 在其PerformMovement方法中添加以下语句

if (thrusterForce != Vector3.zero)
{
    rb.AddForce(thrusterForce);//作用Time.fixedDeltaTime秒:0.02秒
    thrusterForce = Vector3.zero;
}

2.限制玩家视角

 修改PlayerController.cs

添加以下属性

private float cameraRoatationTotal = 0f;//累计转了多少度
[SerializeField]
private float cameraRotationLimit = 85f;

对其PerformRotation方法进行一下修改

private void PerformRotation()
{
    if (yRotation != Vector3.zero)
    {
        rb.transform.Rotate(yRotation);
    }
    if (xRotation != Vector3.zero)
    {
        cam.transform.Rotate(xRotation);
        cameraRoatationTotal += xRotation.x;
        cameraRoatationTotal = Mathf.Clamp(cameraRoatationTotal, -cameraRotationLimit, +cameraRotationLimit);
        cam.transform.localEulerAngles = new Vector3(cameraRoatationTotal, 0f, 0f);
    }
}

3.射击的实现

(1) 创建并编写PlayerWeapon.cs,将其移动至Assets/Scripts/Player

using System;

[Serializable]
public class PlayerWeapon
{
    public string name = "M16";
    public int damage = 10;
    public float range = 100f;
}

(2)在场景中创建空物体“GameManager”,创建并编写GameManager.cs并挂载至空物体“GameManager”

三、飞行和射击_第3张图片三、飞行和射击_第4张图片

  • GameManager.cs
using System;
using UnityEngine;

public class GameManager : MonoBehaviour
{
    private static string info;

    public static void UpdateInfo(String _info)
    {
        info = _info;
    }

    private void OnGUI()
    {
        GUILayout.BeginArea(new Rect(200f,200f,200f,400f));
        GUILayout.BeginVertical();
        GUILayout.Label(info);
        GUILayout.EndVertical();
        GUILayout.EndArea();
    }
}

(3)创建并编写PlayerShooting.cs并将其挂载至Player预制体,将其移至Assets/Scripts/Player

using Unity.Netcode;
using UnityEngine;

public class PlayerShooting : NetworkBehaviour
{
    [SerializeField]
    private PlayerWeapon weapon;
    [SerializeField] 
    private LayerMask mask;

    private Camera cam;
    
    // Start is called before the first frame update
    void Start()
    {
        cam = GetComponentInChildren();
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetButton("Fire1"))
        {
            Shoot();
        }
    }

    private void Shoot()
    {
        RaycastHit hit;
        if (Physics.Raycast(cam.transform.position, cam.transform.forward, out hit,weapon.range,mask))
        {
            ShootServerRpc(hit.collider.name,weapon.damage);
        }
    }

    [ServerRpc]
    private void ShootServerRpc(string hittedName,int damage)
    {
        GameManager.UpdateInfo(transform.name+" hit "+hittedName);
    }
}

(4) 修改NetworkUI.cs,实现“点击按钮后按钮消失”

using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;

public class NetworkManagerUI : MonoBehaviour
{
    [SerializeField] 
    private Button hostBtn;
    [SerializeField] 
    private Button serverBtn;
    [SerializeField] 
    private Button clientBtn;
    
    // Start is called before the first frame update
    void Start()
    {
        hostBtn.onClick.AddListener(() =>
        {
            NetworkManager.Singleton.StartHost();
            DestroyAllButtons();
        });
        serverBtn.onClick.AddListener(() =>
        {
            NetworkManager.Singleton.StartServer();
            DestroyAllButtons();
        });
        clientBtn.onClick.AddListener(() =>
        {
            NetworkManager.Singleton.StartClient();
            DestroyAllButtons();
        });
    }

    private void DestroyAllButtons()
    {
        Destroy(hostBtn.gameObject);
        Destroy(serverBtn.gameObject);
        Destroy(clientBtn.gameObject);
    }
}

4.附录 

(1)测试效果图

三、飞行和射击_第5张图片

(按住空格起飞,朝向任意碰撞体按下鼠标左键,屏幕左上方出现命中提示) 

(2)部分工程文件完整代码

  • PlayerInput.cs
using UnityEngine;

public class PlayerInput : MonoBehaviour
{
    [SerializeField]
    private float speed = 5f;
    [SerializeField] 
    private float thrusterForce = 20f;
    [SerializeField] 
    private PlayerController playerControllor;
    [SerializeField] 
    private float lookSensitivity = 8f;
    [SerializeField] 
    private ConfigurableJoint joint;
    
    // Start is called before the first frame update
    void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;
        joint = GetComponent();
    }

    // Update is called once per frame
    void Update()
    {
        float xMov = Input.GetAxisRaw("Horizontal");
        float yMov = Input.GetAxisRaw("Vertical");

        Vector3 velocity = (transform.right * xMov + transform.forward * yMov).normalized*speed;
        playerControllor.Move(velocity);

        float xMouse = Input.GetAxisRaw("Mouse X");
        float yMouse = Input.GetAxisRaw("Mouse Y");

        Vector3 yRotation = new Vector3(0f, xMouse, 0f)*lookSensitivity;
        Vector3 xRotation = new Vector3(-yMouse, 0f, 0f)*lookSensitivity;
        playerControllor.Rotate(yRotation,xRotation);

        Vector3 force = Vector3.zero;
        if (Input.GetButton("Jump"))
        {
            force = Vector3.up * thrusterForce;
            joint.yDrive = new JointDrive
            {
                positionSpring = 0f,
                positionDamper = 0f,
                maximumForce = 0f,
            };
        }
        else
        {
            joint.yDrive = new JointDrive
            {
                positionSpring = 20f,
                positionDamper = 0f,
                maximumForce = 40f,
            };
        }
        playerControllor.Thrust(force);
    }
}
  • PlayerController.cs 
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    [SerializeField] 
    private Rigidbody rb;
    [SerializeField] 
    private Camera cam;
    
    private Vector3 velocity = Vector3.zero;//速度:每秒钟移动的距离
    private Vector3 yRotation=Vector3.zero;//旋转角色
    private Vector3 xRotation = Vector3.zero;//旋转视角

    private float cameraRoatationTotal = 0f;//累计转了多少度
    [SerializeField]
    private float cameraRotationLimit = 85f;
    
    private Vector3 thrusterForce = Vector3.zero;//向上的推力
    
    public void Move(Vector3 _velocity)
    {
        velocity = _velocity;
    }

    public void Rotate(Vector3 _yRotation, Vector3 _xRotation)
    {
        yRotation = _yRotation;
        xRotation = _xRotation;
    }

    public void Thrust(Vector3 _thrusterForce)
    {
        thrusterForce = _thrusterForce;
    }

    private void PerformMovement()
    {
        if (velocity != Vector3.zero)
        {
            rb.MovePosition(rb.position+velocity*Time.fixedDeltaTime);
        }

        if (thrusterForce != Vector3.zero)
        {
            rb.AddForce(thrusterForce);//作用Time.fixedDeltaTime秒:0.02秒
            thrusterForce = Vector3.zero;
        }
    }

    private void PerformRotation()
    {
        if (yRotation != Vector3.zero)
        {
            rb.transform.Rotate(yRotation);
        }
        if (xRotation != Vector3.zero)
        {
            cam.transform.Rotate(xRotation);
            cameraRoatationTotal += xRotation.x;
            cameraRoatationTotal = Mathf.Clamp(cameraRoatationTotal, -cameraRotationLimit, +cameraRotationLimit);
            cam.transform.localEulerAngles = new Vector3(cameraRoatationTotal, 0f, 0f);
        }
    }
    
    private void FixedUpdate()
    {
        PerformMovement();
        PerformRotation();
    }
}

你可能感兴趣的:(unity,游戏引擎)