三、飞行和射击

news2025/7/3 19:06:05

目录

1.飞行的实现

2.限制玩家视角

3.射击的实现

4.附录


1.飞行的实现

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

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

  • PlayerInput.cs

添加以下属性 

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

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

joint = GetComponent<ConfigurableJoint>();

在其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”

  • 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<Camera>();
    }

    // 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)测试效果图

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

(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<ConfigurableJoint>();
    }

    // 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();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1055199.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【刷题笔记10.2】LeetCode: 罗马数字转整数

LeetCode: 罗马数字转整数 一、题目描述 二、分析 方法一&#xff1a; 将给定字符串s中的"IV", “IX”, “XL”, “XC”, “CD”, “CM” 全部替换为其他字符如&#xff1a;a, b, c, d, e, f 这种&#xff0c;然后就可以遍历累加了。 s s.replace("IV",…

【数据代理+事件处理+计算属性与监视+绑定样式+条件渲染】

数据代理事件处理计算属性与监视绑定样式条件渲染 1 数据代理1.1 回顾Object.defineProperty方法1.2 数据代理 2 事件处理2.1 绑定监听2.2 事件修饰符2.3 键盘事件 3 计算属性与监视3.1 计算属性3.2 监视属性(侦视属性)3.3 watch对比computed 4 绑定样式4.1 绑定class样式4.2 绑…

Linux命令(一)(目录相关)

目录可以更快找到你想要的命令 1. 命令入门2. 常用目录命令(cd、pwd、ls、cp、rm、mkdir)*cd&#xff1a;用来进入到指定的文件夹*常见操作关于绝对路径和相对路径的说明&#xff1a; *pwd&#xff1a;显示当前工作目录的路径*选项用例 *ls&#xff1a;显示目录中文件及其属性信…

数据结构与算法-(7)---栈的应用-(3)表达式转换

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

区块链(8):p2p去中心化之websoket服务端实现业务逻辑

1 业务逻辑 例如 peer1和peer2之间相互通信 peer1通过onopen{ write(Mesage(QUERY_LATEST))} 向peer2发送消息“我要最新的区块”。 peer2通过onMessage收到消息,通过handleMessage方法对消息进行处理。 handleMessage根据消息类型进行处理 RESPONSE_BLOCKCHAIN:返回区块链…

WSL2和ubuntu的安装过程

目录 1.WSL2的安装 2.Ubuntu的安装 3.安装完成后的打开方式 1.WSL2的安装 按下WINX键&#xff0c;选择Windows PowerShell (管理员) 1.1执行以下命令&#xff0c;该命令的作用是&#xff1a;启用适用于 Linux 的 Windows 子系统 dism.exe /online /enable-feature /featur…

BI神器Power Query(25)-- 使用PQ实现表格多列转换(1/3)

实例需求&#xff1a;原始表格包含多列属性数据,现在需要将不同属性分列展示在不同的行中&#xff0c;att1、att3、att5为一组&#xff0c;att2、att3、att6为另一组&#xff0c;数据如下所示。 更新表格数据 原始数据表&#xff1a; Col1Col2Att1Att2Att3Att4Att5Att6AAADD…

经典网络解析(四) transformer | 自注意力、多头、发展

文章目录 1 背景1.1 困境1.2 基本架构 2 嵌入层3 编码器部分3.1 自注意力层3.2 多头注意力机制3.3 LayerNorm归一化层 4 解码器5 transformer的发展6 代码 1 背景 1.1 困境 transformer可以并行训练&#xff0c;也是用来实现attention注意力机制 之前RNN的困境 &#xff08…

【PostgreSQL】【存储管理】表和元组的组织方式

外存管理负责处理数据库与外存介质(PostgreSQL8.4.1版本中只支持磁盘的管理操作)的交互过程。在PostgreSQL中&#xff0c;外存管理由SMGR(主要代码在smgr.c中)提供了对外存的统一接口。SMGR负责统管各种介质管理器&#xff0c;会根据上层的请求选择一个具体的介质管理器进行操作…

【最优化理论】线性规划标准模型的基本概念与性质

我们在中学阶段就遇到过线性规划问题&#xff0c;主要是二维的情况&#xff0c;而求解的方法一般是非常直观、高效的图解法。根据过往的经验&#xff0c;线性规划问题的最优目标值一般在可行域的顶点处取得&#xff0c;那么本文就对这个问题进行更深入的探讨&#xff0c;维度也…

找不到msvcp140.dll解决方法的5个解决方法以及msvcp140.dll丢失原因分析

msvcp140.dll 是 Microsoft Visual C 2017 Redistributable 的一部分&#xff0c;许多应用程序和游戏都需要这个动态链接库&#xff08;DLL&#xff09;才能正常运行。如果您的系统中找不到 msvcp140.dll&#xff0c;您可能会遇到无法打开某些应用程序或游戏的困境。小编将讨论…

运用动态内存实现通讯录(增删查改+排序)

目录 前言&#xff1a; 实现通讯录&#xff1a; 1.创建和调用菜单&#xff1a; 2.创建联系人信息和通讯录&#xff1a; 3.初始化通讯录&#xff1a; 4.增加联系人&#xff1a; 5.显示联系人&#xff1a; 6.删除联系人&#xff1a; ​编辑 7.查找联系人&#xff1a; ​…

nodejs+vue健身服务应用elementui

第三章 系统分析 10 3.1需求分析 10 3.2可行性分析 10 3.2.1技术可行性&#xff1a;技术背景 10 3.2.2经济可行性 11 3.2.3操作可行性&#xff1a; 11 3.3性能分析 11 3.4系统操作流程 12 3.4.1管理员登录流程 12 3.4.2信息添加流程 12 3.4.3信息删除流程 13 第四章 系统设计与…

AWS Lambda Golang HelloWorld 快速入门

操作步骤 以下测试基于 WSL2 Ubuntu 22.04 环境 # 下载最新 golang wget https://golang.google.cn/dl/go1.21.1.linux-amd64.tar.gz# 解压 tar -C ~/.local/ -xzf go1.21.1.linux-amd64.tar.gz# 配置环境变量 PATH echo export PATH$PATH:~/.local/go/bin >> ~/.bashrc …

【小沐学前端】Node.js实现基于Protobuf协议的WebSocket通信

文章目录 1、简介1.1 Node1.2 WebSocket1.3 Protobuf 2、安装2.1 Node2.2 WebSocket2.2.1 nodejs-websocket2.2.2 ws 2.3 Protobuf 3、代码测试3.1 例子1&#xff1a;websocket&#xff08;html&#xff09;3.1.1 客户端&#xff1a;yxy_wsclient1.html3.1.2 客户端&#xff1a…

绘制动图,金星木星月亮太阳绕圆

图&#x1f4ab; input绘制 行星 木星 太阳 地球 金星&#x1f4ab; 地球 月亮各自旋转 1年 角度 360.gif import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation import math import os# 设置中文字体 font_style 宋体 plt.rcParam…

11Spark

1.安装 anaconda 在官网上下载anaconda linux 后缀为.sh的安装包 运行sh ./Anaconda3-2021.05-Linux-x86_64.sh 安装过程&#xff1a; 输入yes后就安装完成了. 验证&#xff1a; 安装完成后, 退出SecureCRT 重新进来: 看到这个base开头表明安装好了. base是默认的虚拟环…

条件查询和数据查询

一、后端 1.controller层 package com.like.controller;import com.like.common.CommonDto; import com.like.entity.User; import com.like.service.UserService; import jakarta.annotation.Resource; import org.springframework.web.bind.annotation.GetMapping; import …

用于YOLO格式分割的咖啡叶病害数据集。

下载链接&#xff1a;https://download.csdn.net/download/qq_40840797/88389334 数据集&#xff0c;一共1164张照片 随机选取几张照片及对应的目标标签 因为健康&#xff0c;所以标签为空

【嵌入式】使用MultiButton开源库驱动按键并控制多级界面切换

目录 一 背景说明 二 参考资料 三 MultiButton开源库移植 四 设计实现--驱动按键 五 设计实现--界面处理 一 背景说明 需要做一个通过不同按键控制多级界面切换以及界面动作的程序。 查阅相关资料&#xff0c;发现网上大多数的应用都比较繁琐&#xff0c;且对于多级界面的…