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

news2024/10/2 6:32:51

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

  • 一、组件的访问
    • (一)组件的调用
    • (二)组件的参数
    • (三)引用别的组件
    • (四)引用脚本组件
    • (五)消息调用
  • 二、物体的访问
    • (一)获取物体
    • (二)父子物体
    • (三)物体的操作
    • (四)练习:俄罗斯方块
  • 三、资源的访问
    • (一)资源的使用
    • (二)资源数组
    • (三)练习:三色球
  • 四、定时调用
    • (一)定时调用
    • (二)定时与线程
    • (三)取消调用
    • (四)练习:红绿灯&加速减速
  • 五、向量
    • (一)向量
    • (二)向量的运算
    • (三)向量测距
    • (四)向量的使用

一、组件的访问

(一)组件的调用

组件 Component,代表一个功能

如,AudioSource 可用于播放音乐、音效。其中,Play on Awake 表示自动播放 在这里插入图片描述

在代码中,也可以用 API 来使其播放音乐

  1. 获取组件 AudioSource 组件(其中,< > 表示泛型,即获取< AudioSorce >类型的组件
    AudioSource audio = this.GetComponent< AudioSorce >( );
  2. 播放
    adio.Play( );
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

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

    // Update is called once per frame
    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            PlayMusic();
        }
    }

    void PlayMusic()
    {
        AudioSource audio = this.GetComponent<AudioSource>();
        if(audio.isPlaying)
        {
            Debug.Log("* 停止播放");
            audio.Stop();
        }
        else
        {
            Debug.Log("* 开始播放音乐 ..");
            audio.Play();
        }
    }
}

在这里插入图片描述


组件的上下顺序,并无影响,可以手工 Move Up / Down,或者直接拖拽
在这里插入图片描述

(二)组件的参数

组件的参数,也可以在代码中访问

例如:AudioClip 音频资源、Mute 是否静音、Loop 是否循环播放、Volume 音量
更多组件:https://docs.unity.cn/cn/2022.3/ScriptReference/AudioSource.html

AudioSource audio = this.GetComponent<AudioSource>();
audio.mute = true;
audio.loop = true;

(三)引用别的组件

在脚本中,也可以引用别的物体下的组件

  • 第一种办法:public GameObject node; 然后,AudioSource audio = node.getComponent< AudioSource >( );
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MainLogic : MonoBehaviour
{
    public GameObject bgmNode;
    
    private void Awake()
    {
       
    }
    // Start is called before the first frame update
    void Start()
    {
        AudioSource audio = bgmNode.GetComponent<AudioSource>();
        audio.Play();
    }

    // Update is called once per frame
    void Update()
    {
        // 访问另一个节点下的 AudioSource 组件

    }
}

在这里插入图片描述

  • 第二种办法:直接引用,在检查器中赋值 public AudioSource bgm;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MainLogic : MonoBehaviour
{
    public AudioSource bgm;
    
    private void Awake()
    {
       
    }
    // Start is called before the first frame update
    void Start()
    {
        bgm.Play();
    }

    // Update is called once per frame
    void Update()
    {
        // 访问另一个节点下的 AudioSource 组件

    }
}

在这里插入图片描述

(四)引用脚本组件

一个脚本里,访问另一个脚本组件。和普通脚本一样:
1. API获取
FanLogic fan = node.getComponent< FanLogic >( );
2. 直接引用(更常用)
public FanLogic fan;

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

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

    // Update is called once per frame
    void Update()
    {
        this.transform.Rotate(0, rotateSpeed * Time.deltaTime, 0, Space.Self);
    }
}

主控程序书写方法1:

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

public class MainLogic : MonoBehaviour
{
    public GameObject fanNode;
    
    private void Awake()
    {
       
    }
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            Dowork();
        }
    }

    void Dowork()
    {
        FanLogic fan = fanNode.GetComponent<FanLogic>();
        fan.rotateSpeed = 180;
    }
}

主控程序书写方法2(更常用):

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

public class MainLogic : MonoBehaviour
{
    public FanLogic fan;
    
    private void Awake()
    {
       
    }
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            Dowork();
        }
    }

(五)消息调用

消息调用 SendMessage以 ‘消息’ 的形式来调用另一个组件,但其实也并非 ‘消息’ ,本质是同步调用

  1. 找到目标节点
    public GameObject target;
  2. 向目标节点发送 ‘消息’
    target.SendMessage( methodName, value )
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

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

    // Update is called once per frame
    void Update()
    {
        this.transform.Rotate(0, rotateSpeed * Time.deltaTime, 0, Space.Self);
    }

    public void DoRotate()
    {
        Debug.Log("** 执行,DoRotate");
        rotateSpeed = 180;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MainLogic : MonoBehaviour
{
    public GameObject fanNode;
    
    private void Awake()
    {
       
    }
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            // 向目标节点发送一个'消息',消息的名字就算FanLogic中对应的函数名
            Debug.Log("** 发送一个消息,DoRotate");
            fanNode.SendMessage("DoRotate");
        }
    }
}

在这里插入图片描述

SendMessage 的内部执行(反射机制):
Step1: 找到 target 节点下的所有组件
Step2: 在组件下寻找 methodName 这个函数

  • 若存在此函数,则调用它
  • 若不存在,则继续查找
  • 若最终无法匹配,则报错

练习:添加无人机,控制起降

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

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

    // Update is called once per frame
    void Update()
    {
        float height = this.transform.position.y;
        float dy = m_speed * Time.deltaTime;

        if(dy > 0 && height < 4)
        {
            this.transform.Translate(0, dy, 0, Space.Self);
        }    
        if(dy < 0 && height > 0)
        {
            this.transform.Translate(0, dy, 0, Space.Self);
        }
    }

    public void Fly()
    {
        m_speed = 1;
    }
    public void Land()
    {
        m_speed = -1;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

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

    void Start()
    {
        
    }

    void Update()
    {
        this.transform.Rotate(0, m_rotateSpeed * Time.deltaTime, 0, Space.Self);
    }

    public void DoRotate()
    {
        m_rotateSpeed = 360 * 3;
    }
    public void DoStop()
    {
        m_rotateSpeed = 0;
    }

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

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

        rotateLogic.DoRotate();
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetKeyDown(KeyCode.W))
        {
            flyLogic.Fly();
        }

        if(Input.GetKeyDown(KeyCode.S))
        {
            flyLogic.Land();
        }

    }
}

在这里插入图片描述


二、物体的访问

(一)获取物体

游戏物体 GameObject,也可以叫节点
1. 按 名称 / 路径 获取(不推荐)

// 若不重名,可以按名称获取
GameObject node = GameObject.Find("旋翼");
// 最好指定全路径
GameObject node = GameObject.Find("无人机/旋翼");

2. 引用获取
添加一个变量,在检查器引用目标 public GameObject wingNode;

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

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

        //GameObject node = GameObject.Find("无人机/旋翼");

        RotateLogic rotateLogic = wingNode.GetComponent<RotateLogic>();
        rotateLogic.DoRotate();
    }

    // Update is called once per frame
    void Update()
    {
      
    }
}

不建议使用 GameObject.Find( )

  • 执行效率底
  • 名字容易输错
  • 不能自适应名字变化,当目标节点改名时会出错

(二)父子物体

场景中的层级关系 / 父子关系,是由 Transform 维持的
1. 获取父级
获取父级

Transform parent = this.transform.parent;

获取父级节点

GameObject parentNode = this.transform.parent.gameObject;

2. 获取子集
获取子级,有几种方式

  • foreach 遍历
foreach(Transform child in transform)
{
	Debug.Log("* 子物体:" + child.name);
}
  • GetChild( ),按索引获取。例如,获取第 0 个子项
Transform child = this.transform.GetChild(0);
Debug.Log("* 子物体:" + child.name);
  • transform.Find( ),按名称查找子项(其中,二级子级应该指定路径
Transform aa = this.transform.Find("aa");
Transform bb = this.transform.Find("bb");
Transform cc = this.transform.Find("bb/cc");

(三)物体的操作

(1)设置新的父级

this.transform.SetParent(other);

另:设为一级节点(没有父级)

this.transform.SetParent(null);

(2)GameObject.setActive( ),显示 / 隐藏

Transform child = this.transform.Find("aa");
if(child.gameObject.activeSelf)
{
	child.gameObject.SetActive(false);
}
else
{
	child.gameObject.SetActive(true);
}

另:transform.Find( “/222” ),其中 / 表示在根目录(场景节点)下查找物体

(四)练习:俄罗斯方块

3D版的俄罗斯方块,按 空格键 切换形状

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

public class PlayerLogic : MonoBehaviour
{
    int m_index = 0; // 表示显示的是哪一个形状

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            ChangeShape();
        }

        // 向前运动 
        float speed = 1;
        this.transform.Translate(0, 0, speed * Time.deltaTime, Space.Self);
    }

    private void ChangeShape()
    {
        // 先把原来的形状,隐藏
        Transform child = this.transform.GetChild(m_index);
        child.gameObject.SetActive(false);

        m_index += 1;
        int count = this.transform.childCount;
        if (m_index >= count)
            m_index = 0;

        // 显示新的形状
        child = this.transform.GetChild(m_index);
        child.gameObject.SetActive(true);
    }
}

三、资源的访问

(一)资源的使用

在脚本中,也可以引用一个资源

例如,AudioClip 音频文件,Texture 纹理贴图,Material 材质

演示:

  1. 准备音频资源文件,预览
  2. 添加脚本 MusicTest.cs(添加变量 public AudioClip audioSuccess
  3. 引用音频资源
  4. 使用 API 播放音频 AudioSource.PlayOneShot( clip ),用于一次性播放音效
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AudioTest : MonoBehaviour
{
    public AudioClip audioSuccess;

    public AudioClip audioFail;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetKeyDown(KeyCode.A))
        {
            AudioSource audioSource = GetComponent<AudioSource>();

            audioSource.PlayOneShot(audioSuccess);
        }

        if (Input.GetKeyDown(KeyCode.D))
        {
            AudioSource audioSource = GetComponent<AudioSource>();

            audioSource.PlayOneShot(audioFail);
        }

    }
}

在这里插入图片描述

(二)资源数组

在脚本中,也可以定义一个数组变量

比如,一个音乐盒,存了多首歌曲 public AudioClip[ ] songs;

演示:创建一个音乐盒,点鼠标随机切换

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

public class MusicBox : MonoBehaviour
{
    public AudioClip[] songs;

    // Start is called before the first frame update
    void Start()
    {
        if (songs == null || songs.Length == 0)
        {
            Debug.Log("* 请在检查器里指定资源");
        }
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            NextSong();
        }
    }

    private void NextSong()
    {
        // 随机播放 (大家也可以改成顺序播放)

        // 在 [min, max) 间随机抽取一个值。不包含max 
        int index = Random.Range(0, songs.Length);
        AudioClip clip = this.songs[index];

        // 播放选中的歌曲
        AudioSource ac = GetComponent<AudioSource>();
        ac.clip = clip;
        ac.Play();

        Debug.Log("* 播放第 " + index + "首歌 , 名字: " + clip.name);
    }
}

在这里插入图片描述

(三)练习:三色球

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

public class SimpleLogic : MonoBehaviour
{
    public Material[] colors;

    // 当前材质序号
    int m_index = 0;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            ChangeColor();
        }
    }

    private void ChangeColor()
    {
        m_index += 1;
        if (m_index >= this.colors.Length)
            m_index = 0;

        // 把选中的材质拿出来
        Material selected = this.colors[m_index];

        // 交给 MeshRenderer 组件
        MeshRenderer rd = GetComponent<MeshRenderer>();
        rd.material = selected;

    }    
}

在这里插入图片描述
也可以使用其他办法,比如,直接修改 Material 的 Albedo 颜色


四、定时调用

(一)定时调用

定时调用 Invoke*,即一般所谓的 ‘定时器’。继承自 MonoBehaviour:

指令解释
Invoke( func, delay )在delay之后执行,只调用一次
InvokeRepeating( func, delay, interval )在delay之后首次执行,然后每隔interval执行一次(循环调用)
IsInvoking( func )是否正在调度中
CanceIInvoke( func )取消调度、从调度队列中移除
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SimpleLogic : MonoBehaviour
{

    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("* Start ..." + Time.time);
        this.Invoke("DoSomething", 1);
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    private void DoSomething()
    {
        Debug.Log("* DoSomething ..." + Time.time);
    }
}

在这里插入图片描述

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

public class SimpleLogic : MonoBehaviour
{

    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("* Start ..." + Time.time);
        // this.Invoke("DoSomething", 1);
        this.InvokeRepeating("DoSomething", 1, 2);
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    private void DoSomething()
    {
        Debug.Log("* DoSomething ..." + Time.time);
    }
}

在这里插入图片描述

  • Start( ) 只执行一次,这里是没有执行完,所以一直在执行,类似多线程
  • fun,函数名是一个字符串(反射机制)

练习:做一个弹跳的小球

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

public class SimpleLogic : MonoBehaviour
{
    public float speed = 1.5f;
    
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("* Start ..." + Time.time);
        // this.Invoke("DoSomething", 1);
        this.InvokeRepeating("DoSomething", 1, 2);
    }

    // Update is called once per frame
    void Update()
    {
        this.transform.Translate(0, speed * Time.deltaTime, 0, Space.Self);
    }

    private void DoSomething()
    {
        Debug.Log("* DoSomething ..." + Time.time);

        this.speed = 0 - speed;
    }
}

(二)定时与线程

InvokeRepeating 定时调用,并没有创建新的线程(Unity引擎核心是单线程的,不必考虑线程、并发、互斥

验证:Start( )、Update( ) 以及定时调用,是在同一个线程

获取当前线程号

using System.Threading;
int threadld = Thread.CurrentThread.ManagedThreadId;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;


public class SimpleLogic : MonoBehaviour
{
    public float speed = 1.5f;
    
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("* Start , 线程ID=" + Thread.CurrentThread.ManagedThreadId);
        // this.Invoke("DoSomething", 1);
        this.InvokeRepeating("DoSomething", 1, 2);
    }

    // Update is called once per frame
    void Update()
    {
        Debug.Log("* Update , 线程ID=" + Thread.CurrentThread.ManagedThreadId);

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

    private void DoSomething()
    {
        Debug.Log("************************** DoSomething , 线程ID=" + Thread.CurrentThread.ManagedThreadId);

        this.speed = 0 - speed;
    }
}

在这里插入图片描述
在这里插入图片描述

参考官方文档的说明:https://docs.unity.cn/cn/2022.3/Manual/ExecutionOrder.html

  • 消息函数 Awake / Start / Update / OnEnable
  • 定时调用 Invoke
  • 协程调用 Coroutine
    在这里插入图片描述

(三)取消调用

  1. 重复调用
    每次 InvokeRepeating,都会添加一个新的调度,若有多个调度,每个调度之间独立,有叠加效果。
  2. 取消调用
指令解释
IsInvoking( fun )判断 func 是否在 Invoke 队列
CanceIInvoke( func )取消 func 的 Invoke 调用
Cancellnvoke( )取消当前脚本的所有 Invoke 调用
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

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

    // Update is called once per frame
    void Update()
    {
        // 点鼠标左键后,开始定时器
        if(Input.GetMouseButtonDown(0))
        {
            // 自己根据实际需要,实现自己的逻辑

            // IsInvoking 判断是否已经在调度队列中
            // CancelInvoke 从调度队列中移除
            // InvokeRepeating 添加一个新的调度到队列中
            if ( IsInvoking("Expand"))
            {
                CancelInvoke("Expand");
            }
            else
            {
                InvokeRepeating("Expand", 1, 1);
            }
        }
    }

    private void Expand()
    {
        Debug.Log("* 变长 。。" + Time.time);

        Vector3 scale = this.transform.localScale;
        scale.y += 1;
        this.transform.localScale = scale;
    }
}

在这里插入图片描述

注:在 Invoke 时,一般要避免重复调用,形如:

if(!IsInvoking(fun))
{
	InvokeRepeating(fun, delay, interval);
}

(四)练习:红绿灯&加速减速

练习1:做一个可以自动切换的红绿灯(红灯4s,绿灯4s,黄灯1s)

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

public class LightLogic : MonoBehaviour
{
    [Tooltip("红、绿、黄按顺序指定")]
    public Material[] colors;

    int m_index = 0; // 红灯开始

    // Start is called before the first frame update
    void Start()
    {
        ChangeColor();
    }

    // Update is called once per frame
    void Update()
    {        
    }

    void ChangeColor()
    {
        // 当前材质
        Material color = this.colors[m_index];
        MeshRenderer renderer = GetComponent<MeshRenderer>();
        renderer.material = color;
        Debug.Log("* Change -> " + m_index + ", time=" + Time.time);
                
        if (m_index == 0)
        {
            // 红 -> 绿,间隔3秒钟
            Invoke("ChangeColor", 4);
        }        
        else if (m_index == 1)
        {
            // 绿 -> 黄,间隔1秒钟
            Invoke("ChangeColor", 4);
        }        
        else if (m_index == 2)
        {
            // 黄 -> 红,间隔1秒钟
            Invoke("ChangeColor", 1);
        }

        // 切换
        m_index++;
        if (m_index >= 3) m_index = 0;
    }
}

在这里插入图片描述

练习2:实现速度渐变的效果

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

public class FanLogic : MonoBehaviour
{
    public float maxRotateSpeed = 720; // 最大转速

    float m_speed = 0; // 当前转速
    bool m_speedUp = false; // true 加速 , false 减速
    
    // Start is called before the first frame update
    void Start()
    {
        InvokeRepeating("AdjustSpeed", 0.1f, 0.1f);   
    }

    // Update is called once per frame
    void Update()
    {
        // 点一下,加速;再点一下,减速
        if(Input.GetMouseButtonDown(0))
        {
            m_speedUp = !m_speedUp;
        }

        if(m_speed > 0)
        {
            this.transform.Rotate(0, m_speed * Time.deltaTime, 0, Space.Self);
        }
    }

    // 调整速度
    private void AdjustSpeed()
    {
       if(m_speedUp)
        {
            if (m_speed < maxRotateSpeed)
                m_speed += 10;
        }
        else
        {
            m_speed -= 10;
            if (m_speed < 0)
                m_speed = 0;
        }
    }
}

五、向量

(一)向量

1. 向量 Vector3,三维向量(x, y, z),求长度的 API:

Vector3 v = new Vector3(3,0,4);
float len = v.magnitude;

2. 单位向量,即长度为1的向量,例如:

Vector3 v1 = new Vector3(1,0,0);
Vector3 v2 = new Vector3(0.6f,0.8f,0);

3. 标准化 Normalize:缩放一个向量,使其长度为1,相关API:

Vector3 v1 = new Vector3(2,2,0);
Vector3 v2 = v1.normalized;

4. 几个常量

Vector3.zero; // 即(0,0,0)
Vector3.up; // 即(0,1,0) y
Vector3.right; // 即(1,0,0) x
Vector3.forward; // 即(0,0,1) z

(二)向量的运算

1. 向量加 / 减法,即 x y z 三个分量分别相加 / 减

Vector3 a = new Vector3(1,3,0);
Vector3 b = new Vector3(4,1,3);
Vector3 c = a + b;
Vector3 d = a - b;

2. 向量乘法,分 3 种

// 1. 标量乘法
b = a * 2;
// 2. 点积
c = Vector3.Dot(a,b);
// 3. 差积
c = Vector3.Cross(a,b);

3. 赋值运算:Vector3 是值类型,可以直接赋值(不能设为 null)

(三)向量测距

向量测距,用于求两物体间的距离,准确的说是轴心点之间的距离。例如

Vector3 p1 = this.transform.position; // 自己位置
Vector3 p2 = target.transform.position; // 目标位置
Vector3 direction = p2 - p1; // 方向向量
float distance = direction.magnitude; // 距离

另:Vector3.Distance( a, b ),也可以求距离,与上面求法原理相同

(四)向量的使用

Vector3 可以直接作为脚本的参数

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

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

    // Update is called once per frame
    void Update()
    {
        // 无论沿着 x y z 都可以一次性搞定
        Vector3 delta = speed * Time.deltaTime;
        this.transform.Translate(delta, Space.Self);
    }
}

在这里插入图片描述


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

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

相关文章

A*搜索算法 双向A*搜索算法 Julia实现

算法概述 抽象的在非负有向边权图 G ( V , E , W ) , W : E → R G (V, E, W), W: E \to \mathbb{R} G(V,E,W),W:E→R 上的 BFS 过程可以看作这样&#xff1a; (1) 设 C C C 点集表示已遍历的点&#xff0c; ∀ n ∈ C , d ( n ) \forall n \in C, d(n) ∀n∈C,d(n) 表示…

Leetcode75- 种花问题

间隔种花 也就是 0 0 0 或者开头 0 0 结尾 0 0 也就是这三个地方可以种花 然后分别判断 最后根据提交结果分析漏掉的情况 比如 n为0 和 数组长度只有一个的情况 使用枚举可以很快解题

技术男的审美反击:UI配置化新纪元

之前常常被甲方的领导说&#xff0c;我们全是一群钢铁直男&#xff0c;一点不懂审美&#xff0c;其实我们心里边想的 “您说得对啊&#xff01;&#xff01;&#xff01;&#xff01;” 这个可能和理工科有关系吧&#xff0c;理工男好像都差不多&#xff0c;所以这次我们就把很…

Vue的学习(二)

目录 一、class及style的绑定 1.v-bind:class绑定类名 绑定class为对象 ​编辑2. v-bind:class绑定类名 绑定class为对象 3.v-bind:class绑定类名 绑定class为数组 1) v-bind:class绑定类名 绑定class为数组 方法一&#xff1a; 2) v-bind:class绑定类名 绑定class为数组…

实验4-2-1 求e的近似值

//实验4-2-1 求e的近似值 /* 自然常数 e 可以用级数 11/1!1/2!⋯1/n!⋯ 来近似计算。 本题要求对给定的非负整数 n&#xff0c;求该级数的前 n1 项和。 输入格式:输入第一行中给出非负整数 n&#xff08;≤1000&#xff09;。 输出格式:在一行中输出部分和的值&#xff0c;保留…

nginx: [error] open() “/run/nginx.pid“ failed (2: No such file or directory)

今天 准备访问下Nginx服务&#xff0c;但是 启动时出现如下报错&#xff1a;&#xff08;80端口被占用&#xff0c;没有找到nginx.pid文件&#xff09; 解决思路&#xff1a; 1、 查看下排查下nginx服务 #确认下nginx状态 ps -ef|grep nginx systemctl status nginx#查看端口…

数据结构——时间和空间复杂度

目录 一、时间复杂度和空间复杂度是什么 二、为什么要有时间复杂度和空间复杂度 三、时间复杂度 四、空间复杂度 一、时间复杂度和空间复杂度是什么 在生活中&#xff0c;我们做一件事情需要花费一定的时间和一定的空间&#xff0c;举一个例子&#xff1a; 一个工厂需要制…

从根儿上学习spring 十一 之run方法启动第四段(5)

图15-AbstractAutowireCapableBeanFactory#doCreateBean方法 我们接着讲doCreateBean方法&#xff0c;之前对循环依赖做了些解释&#xff0c;我们接着往下看populateBean(beanName, mbd, instanceWrapper)方法 图15-572行 这行就是调用populateBean(beanName, mbd, instanceW…

目标检测——YOLOv10: Real-Time End-to-End Object Detection

YOLOv10是在YOLOv8的基础上&#xff0c;借鉴了RT-DETR的一些创新点改进出来的 标题&#xff1a;YOLOv10: Real-Time End-to-End Object Detection论文&#xff1a;https://arxiv.org/pdf/2405.14458源码&#xff1a;https://github.com/THU-MIG/yolov10 1. 论文介绍 在过去的几…

【C语言】详解feof函数和ferror函数

文章目录 前言1. feof1.1 feof函数原型1.2 正确利用函数特性读写文件1.2.1 针对文本文件1.2.2 针对二进制文件 1.3 feof函数的原理1.4 feof函数实例演示 2. ferror2.1 ferror函数原型 前言 或许我们曾在网络上看过有关于feof函数&#xff0c;都说这个函数是检查文件是否已经读…

Windows系统使用内网穿透配置Mysql公网地址实现IDEA远程连接

文章目录 前言1. 本地连接测试2. Windows安装Cpolar3. 配置Mysql公网地址4. IDEA远程连接Mysql5. 固定连接公网地址6. 固定地址连接测试 前言 IDEA作为Java开发最主力的工具&#xff0c;在开发过程中需要经常用到数据库&#xff0c;如Mysql数据库&#xff0c;但是在IDEA中只能…

【Python学习手册(第四版)】学习笔记15-文档(注释、PyDoc等)

个人总结难免疏漏&#xff0c;请多包涵。更多内容请查看原文。本文以及学习笔记系列仅用于个人学习、研究交流。 本文主要介绍程序的文档概念。包括为程序编写的注释&#xff0c;以及内置工具的文档。讲解文档字符串、Python的在线手册等资源、以及PyDoc的help函数和网页接口。…

蒙电通无人机航线规划系统 雷达点云电力应用软件

蒙电通无人机航线规划系统&#xff0c;它可进行标记杆塔、切档、自动对点云数据分类和点云抽稀等处理&#xff0c;按3张或6张照片自动生成航线&#xff0c;或按自定义航线模型生成航线&#xff0c;支持安全性检测。在满足当地巡检标准的前提下&#xff0c;系统操作非常简便。 …

llama神经网络的结构,llama-3-8b.layers=32 llama-3-70b.layers=80; 2000汉字举例说明

目录 llama-3-8b.layers=32 llama-3-70b.layers=80 llama神经网络的结构 Llama神经网络结构示例 示例中的输入输出大小 实际举例说明2000个汉字文本数据集 初始化词嵌入矩阵 1. 输入层 2. 嵌入层 3. 卷积层 4. 全连接层 llama-3-8b.layers=32 llama-3-70b.laye…

跑深度学习模型Ⅲ:正确安装与torch版本对应的其他torch包

pytorch的正确安装可以回看我前面的博客跑深度学习模型Ⅱ&#xff1a;一文安装正确pytorch及dgl-CSDN博客 这篇博客将安装torch_grometric&#xff0c;torch_scatter, torch_sparse, torch_cluster库 1. 查看自己的torch版本 进入cmd 切换到要用的python环境中&#xff0c;输…

ADB Installer 0 file(s)copied

在为泡面神器刷安卓&#xff0c;做准备工作装ADB时报错了&#xff0c;以下是报错提示 再用cmd命令adb version验证下&#xff0c;提示adb不是有效命令&#xff0c;百分百安装失败了&#xff0c;往上各种搜索查询均没有对症的&#xff0c;其中也尝试了安装更新版本的&#xff0c…

2024版本IDEA创建Servlet模板

IDEA 版本 2024.1.4 新版本的 IDEA 需要自己创建 Servlet 模板 旧版本 IDEA 看我这篇文章&#xff1a;解决IDEA的Web项目右键无法创建Servlet问题_2024idea无法创建servlet项目-CSDN博客文章浏览阅读216次&#xff0c;点赞7次&#xff0c;收藏3次。解决IDEA的Web项目右键无法创…

AGI思考探究的意义、价值与乐趣 Ⅴ

搞清楚模型对知识或模式的学习与迁移对于泛化意味什么&#xff0c;或者说两者间的本质&#xff1f;相信大家对泛化性作为大语言模型LLM的突出能力已经非常了解了 - 这也是当前LLM体现出令人惊叹的通用与涌现能力的基础前提&#xff0c;这里不再过多赘述&#xff0c;但仍希望大家…

【Python学习手册(第四版)】学习笔记14-迭代器和列表解析(一)

个人总结难免疏漏&#xff0c;请多包涵。更多内容请查看原文。本文以及学习笔记系列仅用于个人学习、研究交流。 本文主要以通俗易懂的语言介绍迭代器&#xff08;文件迭代、手动迭代iter和next等&#xff09;&#xff0c;列表解析式包括基础知识包括写法、文件上使用列表解析…

繁简之争:为什么手机芯片都是 ARM

RISC 和 CISC 指令集 之前的文章《揭秘 CPU 是如何执行计算机指令的》中说到&#xff0c;如果从软件的角度来讲&#xff0c;CPU 就是一个执行各种计算机指令&#xff08;Instruction Code&#xff09;的逻辑机器。 计算机指令集是计算机指令的集合&#xff0c;包括各种类型的…