【Unity】3D功能开发入门系列(三)

news2024/11/15 7:34:09

Unity3D功能开发入门系列(三)

  • 一、运动脚本
    • (一)物体的运动
    • (二)相对运动
    • (三)运动的方向
  • 二、旋转脚本
    • (一)物体的旋转
    • (二)相对旋转
    • (三)自传与公转
    • (四)官方文档
  • 三、脚本的运行
    • (一)脚本的运行
    • (二)消息函数
    • (三)脚本执行顺序
    • (四)主控脚本
  • 四、脚本的参数
    • (一)脚本的参数
    • (二)参数的赋值
    • (三)值类型
    • (四)引用类型
    • (五)运行时调试
  • 五、鼠标键盘输入
    • (一)鼠标输入
    • (二)屏幕坐标
    • (三)键盘输入

一、运动脚本

准备工作:

  • 布置测试场景,添加小火车
    在这里插入图片描述
  • 添加脚本 SimpleLogic,控制小火车移动

(一)物体的运动

一般使用 transform.Translate( ),实现相对运动
transform.Translate( dx, dy, dz, …) ,其中 dx, dy, dz 是坐标增量

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MoveLogic : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        float speed = 1;
        float distance = speed * Time.deltaTime;

        //Vector3 pos = this.transform.localPosition;
        //pos.z += distance; // 0.005f;
        //this.transform.localPosition = pos;

        this.transform.Translate(distance, 0, distance);
    }
}

在这里插入图片描述

(二)相对运动

transform.Translate( dx, dy, dz, space),其中第 4 个参数:

  • Space.World,相对于 世界坐标系
    在这里插入图片描述

  • Space.Self,相对于 自身坐标系(本地坐标系)<更常用>
    在这里插入图片描述

在建模时,要求物体的 脸的朝向 与物体 +Z轴 一致
在这里插入图片描述

(三)运动的方向

使物体朝着目标方向移动(这里以小红旗为例),到达目标后停下来
在这里插入图片描述
在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static Unity.IO.LowLevel.Unsafe.AsyncReadManagerMetrics;

public class MoveLogic : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        // 获取目标物体
        GameObject flag = GameObject.Find("红旗");
        // 转向目标
        this.transform.LookAt(flag.transform);
    }

    // Update is called once per frame
    void Update()
    {
        GameObject flag = GameObject.Find("红旗");
        Vector3 p1 = this.transform.position;
        Vector3 p2 = flag.transform.position;
        Vector3 p = p2 - p1;
        float distance = p.magnitude; // magnitude 取向量的模

        if(distance > 0.3f)
        {
            float speed = 2;
            float move = speed * Time.deltaTime;
            this.transform.Translate(0, 0, move, Space.Self);
        }
    }
}

  • 其中:
    GameObject.Find( name_or_path),根据 名字 / 路径 查找物体
    transform.LookAt( target),使物体的 Z轴 指向 target 物体(若目标在空中,火车就原地起飞了)
    Space.self,沿物体自身坐标系的轴向运动
  • 如果想让视角随着物体运动
    在这里插入图片描述

二、旋转脚本

(一)物体的旋转

给物体调转一个旋转的角度

  • Quaternion 四元组(x, y, z, w)
    transform.rotation = … 不便操作,官方也不建议使用
  • 欧拉角 Euler Angle
    transform.eulerAngles = new Vector3( 0, 45, 0);
    transform.localEulerAngles = new Vector( 0, 45, 0);

注:new Vector( 0, 45, 0)、new Vector( 0, 405, 0)、new Vector( 0, -315, 0) 效果相同

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RotateLogic : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Application.targetFrameRate = 60;
    }

    // Update is called once per frame
    void Update()
    {
        float rotateSpeed = 60; // 每秒转 60°

        Vector3 angles = this.transform.localEulerAngles;
        angles.y += rotateSpeed * Time.deltaTime; //0.5f;
        this.transform.localEulerAngles = angles;
    }
}

在这里插入图片描述

(二)相对旋转

Rotate( ),旋转一个相对角度
transform.Rotate( dx, dy, dz, space)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RotateLogic : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Application.targetFrameRate = 60;
    }

    // Update is called once per frame
    void Update()
    {
        float rotateSpeed = 60; // 每秒转 60°

        //Vector3 angles = this.transform.localEulerAngles;
        //angles.y += rotateSpeed * Time.deltaTime; //0.5f;
        //this.transform.localEulerAngles = angles;

        this.transform.Rotate(0, rotateSpeed * Time.deltaTime, 0, Space.Self);
    }
}

(三)自传与公转

  • 自转,绕着自身轴旋转
  • 公转,围绕另一个物体旋转

当父物体转动时,带动子物体一并旋转

在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/** 此脚本挂在卫星上
 * 
 */
public class MoonLogic : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        float rotateSpeed = 60;

        // 找到父物体
        Transform parent = this.transform.parent;

        // 控制父物体旋转
        parent.Rotate(0, rotateSpeed* Time.deltaTime, 0, Space.Self);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/** 地球运动的脚本
 * 
 */
public class PlanetLogic : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        float rotateSpeed = 10; 

        this.transform.Rotate(0, rotateSpeed * Time.deltaTime, 0, Space.Self);
    }
}

在这里插入图片描述

(四)官方文档

手册 Manual + Script API:https://docs.unity.cn/cn/2022.3/ScriptReference/index.html


三、脚本的运行

(一)脚本的运行

Unity 是一款游戏引擎,用于驱动游戏逻辑
(1)场景的加载过程(伪代码)

  1. 创建节点:GameObject node = new GameObject( )
  2. 实例化组件:MeshRendered comp = new MeshRender( )
  3. 实例化脚本组件:SimpleLogic script1 = new SimpleLogic( )
  4. 调用事件函数初始化 script1.Start( )、帧更新 script1.Update( )

注:Unity 是一个纯面向对象的框架,对象由框架创建

(2)再添加一个物体,也挂载相同的 SimpleLogic 脚本(伪代码)

  1. GameObject node2 = new GameObject( )
  2. SimpleLogic script2 = new SimpleLogic( )
  3. script2.Start( )
  4. script2.Update( )

其中,又创建了一个 SimpleLogic 实例,挂在了新的节点下

(二)消息函数

所有的脚本,一般应继承于 MonoBehavour消息函数,或称 事件函数,一些回调函数

常见的消息函数:

函数说明
Awake初始化,仅执行一次
Start初始化,仅执行一次
Update帧更新,每帧调用一次
OnEnable每当组件启用时调用
OnDisable每当组件禁用时调用

  • Awake 只执行一次,总是先于 Start 调用,且总是调用(即使组件被禁用)
  • Start 只执行一次,第一次启用时调用,若组件被禁用,就不调用

(三)脚本执行顺序

Unity 默认是单线程的协程异步
1. 消息函数的调用顺序:
第1阶段初始化:script1.Awake( ),script2.Awake( ),…
第2阶段初始化:script1.Start( ),script2.Start( ),…
帧更新:script1.Update( ),script2.Update( ),…

2. 脚本优先级 Script Execution Order
默认的,所以脚本的优先级为0,无特定顺序(执行顺序和在 Hierarchy 中的顺序无关)

优先级的设定:

  1. 选中一个脚本,打开 Execution Order 对话框
  2. 点 + 按钮,添加要调整优先级的脚本
  3. 指定优先级,值越小、优先级越高;或者,直接拖动调节顺序
    在这里插入图片描述在这里插入图片描述

一般的,并不需要显示设置 Execution Order,默认即可

(四)主控脚本

主控脚本,即游戏的主控逻辑,设置一些全局性的设置、全局性的逻辑,其他的脚本就只用负责各种的功能了
在这里插入图片描述


四、脚本的参数

(一)脚本的参数

脚本的参数,用于控制脚本组件的功能
在这里插入图片描述
添加下面这行代码到 RotateLogic 的全局中后:

public float rotateSpeed = 30f;

在这里插入图片描述

参数的用法:

  1. 参数必须public,才可以在检查器中显示
  2. 参数的名称,即变量名 rotateSpeed -> Rotate Speed
  3. 参数的默认值,即变量的默认值(可以 Reset 菜单重置)
  4. 参数的工具提示,可以用 [ Tooltip( ) ] 指定,如:[ Tooltip(" 旋转速度 ") ]
    在这里插入图片描述
[Tooltip("这个是Y轴向的角速度")]
public float rotateSpeed = 30f;

这样同一个脚本就可以在多个物体上使用,其相关参数可以通过检查器调节

(二)参数的赋值

以下按时间顺序:

  1. 定义默认值 public float rotateSpeed = 30f;
  2. 检查器中赋值 script.rotateSpeed = 180f; // 由 Unity 框架对参数赋值
  3. 在 Awake 中初始化
  4. 在 Start 中初始化
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RotateLogic : MonoBehaviour
{
    [Tooltip("这个是Y轴向的角速度")]
    public float rotateSpeed = 30f;

    private void Awake()
    {
        this.rotateSpeed = 90;
        Debug.Log("** Awake , rotateSpeed=" + this.rotateSpeed);
    }
   
    void Start()
    {
        this.rotateSpeed = 120;
        Debug.Log("** Start , rotateSpeed=" + this.rotateSpeed);
    }

    void Update()
    {
        // float speed = 30f; // 每秒转
        Debug.Log("** 速度=" + this.rotateSpeed);
        this.transform.Rotate(0, rotateSpeed * Time.deltaTime, 0, Space.Self);
    }

}

伪代码表示 (值最终是120)
RotateY script = new RotateY( ) // 30
script.rotateSpeed = 180f // 180
script.Awake( ) // 90
script.Start( ) // 120
在这里插入图片描述

(三)值类型

参数的类型,分为 值类型(栈上)、引用类型(堆上)
值类型,如 int,float,bool
值类型 (struct) ,如 Vector3,Color
引用类型 (class) ,如 GameObject,Transform,MeshRendered

  1. 值类型的特点:
  • 本身是一个值,可以直接赋值
  • 若为赋值,则默认为 0
  • 不能为 null
  1. 结构体 struct,也是值类型(特点与1同)
    设初始值要new eg. public Vector3 rotateSpeed = new Vector3(1, 1, 1)

其实,C# 里面,int(struct System.int32)、float(struct System.Single) 本质也是 struct 类型;string 原则上属于 class 类型。C# 内部本质只有 struct 和 class 两种类型

(四)引用类型

参数也可以是引用类型

  • 节点,GameObject
  • 组件,如 Transform、MeshRenderer、AudioSourse …
  • 资源,如 Material、Texture、AudioClip
  • 数组类型
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TrainLogic : MonoBehaviour
{
    public GameObject target;
    
    void Start()
    {
        Application.targetFrameRate = 60;

        this.transform.LookAt(target.transform);
    }

    void Update()
    {
        Vector3 p1 = this.transform.position;
        Vector3 p2 = target.transform.position;
        Vector3 p = p2 - p1;
        float distance = p.magnitude;

        if(distance > 0.3f)
        {
            float speed = 2;
            float move = speed * Time.deltaTime;
            this.transform.Translate( 0, 0, move, Space.Self);
        }
    }
}

在这里插入图片描述

(五)运行时调试

在游戏运行时,可以对 物体 / 组件 进行 实时调试,但是在运行模式下,所有的参数不能保存到场景。保存参数的办法:

  • Play Mode 下,暂停一下游戏,组件 Copy Component
  • Edit Mode 下,组件 Paste Component Values
    在这里插入图片描述

五、鼠标键盘输入

(一)鼠标输入

游戏的输入,可以来自鼠标、键盘、触摸屏、游戏手柄

鼠标输入相关 API:

指令含义
Input.GetMouseButtonDown( )探测用户是否按下鼠标
Input.GetMouseButtonUp( )探测用户是否抬起鼠标
Input.GetMouseButton( )状态探测,探测用户是否一直按着鼠标

1. 事件探测

其中,0 左键 / 1 右键 / 2 中键,且鼠标事件只触发一次,不会重复触发

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FanLogic : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            Debug.Log("** 鼠标按下");
        }
        if(Input.GetMouseButtonUp(0))
        {
            Debug.Log("** 鼠标抬起");
        }
        
        float speed = 180;
        this.transform.Rotate(0, speed * Time.deltaTime, 0, Space.Self);
    }
}

在这里插入图片描述

练习:鼠标按下时,旋转;鼠标松开时,停止 。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FanLogic : MonoBehaviour
{
    float m_speed = 0;
    
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            Debug.Log("** 鼠标按下");
            m_speed = 180;
        }
        if(Input.GetMouseButtonUp(0))
        {
            Debug.Log("** 鼠标抬起");
            m_speed = 0;
        }
        
        // float speed = 180;
        this.transform.Rotate(0, m_speed * Time.deltaTime, 0, Space.Self);
    }
}

:操作时,鼠标应该在 Game 窗口里点击,不是 Scene窗口

2. 状态探测

区分: 事件探测 VS 状态探测
鼠标事件,只触发一次:Input.GetMouseButtonDown() 、Input.GetMouseButtonUp()
鼠标状态,表示当前是否正在被按下:Input.GetMouseButton()

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FanLogic : MonoBehaviour
{
    float m_speed = 0;
    
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetMouseButton(0))
        {
            Debug.Log("** 鼠标按下ing,正被按下");
            m_speed = 180;
        }
        else
        {
            m_speed = 0;
        }
        
        // float speed = 180;
        this.transform.Rotate(0, m_speed * Time.deltaTime, 0, Space.Self);
    }
}

在这里插入图片描述

  • 如果要实现加减速等更复杂的游戏逻辑,事件显然比状态好
  • 鼠标事件是全局的,每个脚本 互不影响,大家都可以探测,不会被哪个物体截断
    在这里插入图片描述

(二)屏幕坐标

1. 鼠标按下时,取得鼠标的当前所在位置(其中,mousePosition 是鼠标在屏幕上的坐标):
在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeLogic : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        int width = Screen.width;
        int height = Screen.height;
        Debug.Log("** 屏幕 : " + width + ", " + height);
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Vector3 mousePos = Input.mousePosition;
            Debug.Log("** 鼠标位置" + mousePos);
        }
    }
}

在这里插入图片描述
2. 一个物体,在屏幕上的位置
其中所谓 屏幕,相对于摄像机而言的,实际上是指摄像头的屏

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeLogic : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        //int width = Screen.width;
        //int height = Screen.height;
        //Debug.Log("** 屏幕 : " + width + ", " + height);

        Vector3 pos = this.transform.position;
        Vector3 screenPos = Camera.main.WorldToScreenPoint(pos);
        Debug.Log("** 物体的屏幕坐标:" + screenPos);
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Vector3 mousePos = Input.mousePosition;
            Debug.Log("** 鼠标位置" + mousePos);
        }
    }
}

在这里插入图片描述

练习:物体运动时,检查是否超出屏幕的边界

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeLogic : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        //int width = Screen.width;
        //int height = Screen.height;
        //Debug.Log("** 屏幕 : " + width + ", " + height);

        Vector3 pos = this.transform.position;
        Vector3 screenPos = Camera.main.WorldToScreenPoint(pos);
        Debug.Log("** 物体的屏幕坐标:" + screenPos);
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Vector3 mousePos = Input.mousePosition;
            Debug.Log("** 鼠标位置" + mousePos);
        }

        Vector3 pos = this.transform.position;
        Vector3 screenPos = Camera.main.WorldToScreenPoint(pos);
        if(screenPos.x < 0 || screenPos.x > Screen.width)
        {
            Debug.Log("** 物体已出屏幕边界");
        }

        float speed = 4;

        transform.Translate(speed*Time.deltaTime, 0, 0, Space.World);
    }
}

在这里插入图片描述

(三)键盘输入

相关 API:

指令解释
Input.GetKeyDown( key )按键事件,按下
Input.GetKeyUp( key )按键事件,抬起
Input.GetKey( key )按键状态,是否正被按下

演示:当按下 W 键时,向前运动
键值常量,可以参考官方文档:https://docs.unity.cn/cn/2022.3/ScriptReference/KeyCode.html
KeyCode.A:A
KeyCode.Space:空格
KeyCode.LeftArrow:向左的箭头键…
在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FlyLogic : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        float zSpeed = 0;
        if(Input.GetKey(KeyCode.W))
        {
            // Debug.Log("* 按键 w 被按下");
            zSpeed = 1;
        }    
        this.transform.Translate(0, 0, zSpeed * Time.deltaTime, Space.Self);
    }
}

:运动游戏时,如果发现按键没有反应,应该先用鼠标点一下 Game 窗口,然后才能获得输入焦点


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

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

相关文章

图像相关的基础知识【RGB和RGBA】—附python代码实现

文章目录 1、图像基础知识2、像素和通道的理解3、RGB和RGBARGB (Red, Green, Blue)RGBA (Red, Green, Blue, Alpha)应用场景 4、H,W,C5、小结 &#x1f343;作者介绍&#xff1a;双非本科大三网络工程专业在读&#xff0c;阿里云专家博主&#xff0c;专注于Java领域学习&#x…

aurora8b10b ip的使用(framing接口下的数据回环测试)

文章目录 一、Aurora8B/10B协议二、时钟、复位与状态指示1、时钟2、复位3、状态指示 三、数据发送、接受接口&#xff08;1&#xff09;AXI4-Stream位排序&#xff08;2&#xff09;Streaming接口&#xff08;3&#xff09;Framing接口&#xff08;帧传输接口&#xff09; 四、…

C++ | Leetcode C++题解之第319题灯泡开关

题目&#xff1a; 题解&#xff1a; class Solution { public:int bulbSwitch(int n) {return sqrt(n 0.5);} };

Python | Leetcode Python题解之第318题最大单词长度乘积

题目&#xff1a; 题解&#xff1a; class Solution:def maxProduct(self, words: List[str]) -> int:masks defaultdict(int)for word in words:mask reduce(lambda a, b: a | (1 << (ord(b) - ord(a))), word, 0)masks[mask] max(masks[mask], len(word))return…

索引:SpringCloudAlibaba分布式组件全部框架笔记

索引&#xff1a;SpringCloudAlibaba分布式组件全部框架笔记 一推荐一套分布式微服务的版本管理父工程pom模板&#xff1a;Springcloud、SpringCloudAlibaba、Springboot二SpringBoot、SpringCloud、SpringCloudAlibaba等各种组件的版本匹配图&#xff1a;三SpringBoot 3.x.x版…

字符串相关函数

文章目录 &#x1f34a;自我介绍&#x1f34a;strcpy 字符串拷贝函数&#x1f34a;strcat 字符串连接函数&#x1f34a;strlen 字符串长度计算函数&#x1f34a;strcmp 字符串比较函数 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以&#xff1a;点赞关注评论收藏&…

C++ | Leetcode C++题解之第318题最大单词长度乘积

题目&#xff1a; 题解&#xff1a; class Solution { public:int maxProduct(vector<string>& words) {unordered_map<int,int> map;int length words.size();for (int i 0; i < length; i) {int mask 0;string word words[i];int wordLength word.s…

[Git][基本操作]详细讲解

目录 1.创建本地仓库2.配置 Git3.添加文件1.添加文件2.提交文件3.其他 && 说明 4.删除文件5.跟踪修改文件6.版本回退7.撤销修改0.前言1.未add2.已add&#xff0c;未commit3.已add&#xff0c;已commit 1.创建本地仓库 创建⼀个Git本地仓库&#xff1a;git init运行该命…

模型 ESBI(财富四象限)

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。财富自由之路的4个阶段。 1 ESBI模型的应用 1.1 一名工程师的财富自由之路 有一个名叫张伟的软件工程师&#xff0c;他在一家大型科技公司工作&#xff08;E象限&#xff09;。随着时间的推移&#…

模型量化技术综述:揭示大型语言模型压缩的前沿技术

大型语言模型&#xff08;LLMs&#xff09;通常因为体积过大而无法在消费级硬件上运行。这些模型可能包含数十亿个参数&#xff0c;通常需要配备大量显存的GPU来加速推理过程。 因此越来越多的研究致力于通过改进训练、使用适配器等方法来缩小这些模型的体积。在这一领域中&am…

electron-updater实现electron全量更新和增量更新——渲染进程交互部分

同学们可以私信我加入学习群&#xff01; 正文开始 前言更新功能所有文章汇总一、监听页面渲染完毕1.1 myApi.handleCheckPcUpdate检查更新1.2myApi.onPcUpdateProgress接收下载信息1.3myApi.onPcDownloaded监听下载完毕事件 二、立即更新三、跳过更新四、打开更新模块总结 前言…

打卡第32天------动态规划

坚持了一个月了,骑马找马,要坚持不懈呀✊ 一、动态规划理论基础 1、什么是动态规划?英文:Dynamic Programming,简称DP。 如果某一问题有很多重叠子问题,使用动态规划是最有效的。 所以动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有…

JVM—虚拟机类加载时机与过程

参考资料&#xff1a;深入理解Java虚拟机&#xff1a;JVM高级特性与最佳实践&#xff08;第3版&#xff09;周志明 1. 类加载的时机 一个类型从被加载到虚拟机内存开始&#xff0c;到卸载出内存为止&#xff0c;它的生命周期会经历加载、验证、准备、解析、初始化、使用、卸载…

netapp内网穿透

1. 注册netapp账号 NATAPP-内网穿透 基于ngrok的国内高速内网映射工具 2. 购买隧道&#xff0c;要求不高的话可以使用这个免费的 3.设置隧道 主要设置你想通过公网访问你的本地端口号 4.点击我的隧道&#xff0c;注意这里的authtoken&#xff0c;后面会用到 5.本地下载netap…

[E二叉树] lc572. 另一棵树的子树(dfs+前中序判断+树哈希+树上KMP+好题)

文章目录 1. 题目来源2. 题目解析 1. 题目来源 链接&#xff1a;572. 另一棵树的子树 2. 题目解析 看到这个题目就感觉不简单&#xff0c;因为写了写 dfs 版本的&#xff0c;发现好像不太会… 还是简单粗暴一点&#xff0c;直接搞一个 前序中序&#xff0c;进行判断即可。我…

应急响应-Web3

打开虚拟机之后&#xff0c;运行解题系统&#xff1a; 共有三个问题&#xff01; 攻击者的两个IP地址 首先我们看到机器的桌面上还是存在phpstudy&#xff0c;那就还是先去看看是不是从web层面进行的攻击&#xff0c;上传webshell从而getshell。 利用D盾尝试对phpstudy目录进…

Python | Leetcode Python题解之第319题灯泡开关

题目&#xff1a; 题解&#xff1a; class Solution:def bulbSwitch(self, n: int) -> int:return int(sqrt(n 0.5))

redis面试(四)持久化

什么是持久化&#xff1f; 由于redis是基于内存操作的轻量型数据库&#xff0c;所以如果发生宕机重启这种事情&#xff0c;存储的数据就会直接丢失&#xff0c;如果在里面存储了没有备份的数据&#xff0c;那么确实会对我们的业务造成一定影响。 所以我们要通过持久化的手段&a…

Java中interrupted()与isInterrupted()的区别

Java中interrupted&#xff08;&#xff09;与isInterrupted&#xff08;&#xff09;的区别 1、interrupted()方法1.1 示例 2、isInterrupted() 方法2.1 示例 3、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在Java多线程编程中&a…