unity入门学习笔记

文章目录

  • unity学习笔记
    • 熟悉界面
      • 窗口页面快捷键
      • 视图特点
      • 移动、旋转、缩放快捷键
      • 聚焦和隐藏
    • 一些基本概念
      • 模型
        • 模型的导入
        • 一些补充
      • 资源文件
        • 资源包的导出
        • 资源包的导入
      • 轴心
      • 物体的父子关系
      • 空物体
      • Global与local
      • pivot与center
    • 组件
    • 脚本基础
        • 我的第一个脚本
      • 获取脚本组件
        • 本地坐标
        • 播放模式
      • 帧更新
        • 帧观察的方法
      • 物体运动
        • 让gameObject动起来
        • 让gameObject匀速运动
        • 物体运动优化
        • 坐标系运动(重要)
        • 转向并移动
      • 物体旋转
        • 设置物体转动
        • 实现动态旋转
        • 相对旋转(重要)
        • 自转与公转
        • 分析公转模型关系
        • 脚本的运行
        • 消息函数
          • 常见的消息函数
          • 消息函数的顺序
        • 脚本执行顺序
        • 主控脚本
        • 脚本参数
          • 脚本参数用法
          • 示例代码
          • **脚本参数的赋值与最终取值**示例
          • 脚本参数类型
      • AudioSource组件
        • 脚本中使用API播放音乐
        • 代码实现
        • 介绍AudioSource插件上面的组件
        • 代码实现
        • 引用别的物体的组件
        • 示例(不常用)
        • 示例(常用)
      • 获取脚本组件
        • 通过游戏主控节点引用脚本组件
        • 通过游戏组件引用脚本组件
      • 获取游戏物体
      • 获取父级和子级节点
      • 通过脚本设置音频(不通过组件)
      • 定时器调用
        • 取消定时器
    • 向量
        • 获取向量长度
        • 单位向量
        • 标准化向量
        • 向量相关的常量unity定义
      • 向量的运算
        • 向量的加法
        • 向量的减法
        • 向量的乘法
        • 向量的赋值
      • 向量测距
      • * 示例:用向量指定物体移动
    • 预制体(Prefabs)
      • 预制体的创建
      • 预制体的作用
      • 预制体的编辑
    • 动态创建节点
        • 动态创建实例
        • 动态初始化实例
        • 动态销毁实例(在预制体内定义)
        • 实例的销毁
    • 运行时调试
      • 调试时参数的保存
    • unity的运作方式:单线程
  • 练习项目
    • 练习1:自定义音乐盒
    • 练习2:变色小球
    • 练习3:往复运动的小球
    • 练习4:闪烁灯

unity学习笔记

熟悉界面

重置界面布局:Windows --> layout --> default

窗口页面快捷键

alt + 鼠标左键:绕中心点旋转视图

alt + 鼠标右键:绕中心点缩放视图

alt + 鼠标中键:平移视图

鼠标滑轮:缩放视图

(选中物体后) + f : 使选中的物体变成视图中心

视图特点

透视视图(perspective):近大远小

作用优点:发生透视畸变

正交视图(orthographic):等距视图

作用优点:容易使物体对齐

移动、旋转、缩放快捷键

W、E、R — > 移动、旋转、缩放

聚焦和隐藏

聚焦:之前有提到过;快捷键就是f,也可以在层级窗口中双击实现

隐藏:

一些基本概念

模型

网格Mesh,存储了形状的数据

模型的形状由若干个小面围成的

模型是中空的

Mesh中包含了面、顶点坐标、法向等数据

另外unity中的模型都是由多个三角面围成的

模型的导入

unity支持的模型文件类型为:.fbx

unity支持的贴图文件类型为:.psd

一些补充

平面特点:正面可见(法向),背面透明,没有厚度

所有unity自带的模型也都具有这样的特点,这是因为unity中的模型只渲染了外面

unity自带的模型都自带了一个材质

资源文件

Asset目录下的文件,称为资源文件

常见的类型:

模型文件Model(*.fbx)

图片文件Texture(*.jpg/png/psd/tif)

音频文件AudioClip(*.mp3/wav/aiff)

脚本文件Script(*.cs)

材质文件(*.mat)

场景文件(*.unity)

资源包的导出

unity会自动将所有的依赖资源一起导出成一个你自己命名的资源包

资源包的导入

拖过来就好

轴心

轴心(pivot):对模型进行平移、旋转、缩放的时候都是围绕着轴心点进行的。几何图形的轴心点就是它的几何中心

注意:建模软件可以自己定义轴心点。所以轴心点不一定是自己生成的

物体的父子关系

解释:物体的父节点和子节点的关系

拖动3D模型(子 – > 父)

特点:

  1. 移动父节点(模型),子节点也会跟随移动
  2. 删除父节点(模型),子节点也会被删除

理解

相对坐标:当模型成为某个模型的子节点的时候,子节点坐标从绝对坐标变成了相对坐标

空物体

主要用于两个不好确定父子关系的模型。可以将空物体作为两个模型的父节点,两个模型便可以无损地相对移动

Global与local

global

local

坐标轴称谓:

y轴称为up,z轴称为forward,x轴称为right;一般来说:物体正面需要和z轴方向一致

pivot与center

操作基准点:前者以轴心点作为基准点,后者为几何中心点

默认为pivot

组件

基本的组件

Mesh Renderer:网格渲染器

Light:光照显示

Mesh Filter:网格过滤器

组件映射了模型的功能,你需要一个节点具有什么样的功能,你就可以给组件挂载相对应的组件。

AudioSource:播放音乐,直接将对应音乐拖入AudioClip属性

Transform:变换组件

  • Position,位置(相对坐标)
  • Rotation,旋转(欧拉角)
  • Scale,缩放

特点:

  • 所有物品都有
  • 不能被删除

Camera:负责拍摄游戏画面

PS:修改布局 layout -> 2by3 可以将编辑窗口和游戏窗口放在同一界面显示

摆放摄像机:选中你想要移动的摄像机 GameObject -> Align With View

​ 快捷键: ctrl + shift + F

脚本基础

右键在Asset目录下面创建Scripts文件夹然后新建脚本

我的第一个脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SimpleLogic : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){Debug.Log(" ** 我的第一个脚本");}// Update is called once per framevoid Update(){}
}

前一个方法表示组件在加载的时候运行,后面一个方法在组件更新的时候运行

获取脚本组件

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SimpleLogic : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){Debug.Log(" ** 我的第一个脚本");// 获取当前脚本所在物体本身GameObject obj = this.gameObject;// 获取物体的名字string name = obj.name;Debug.Log(" ** 物体名字" + name);// 获取当前物体的transform组件Transform transform = this.gameObject.transform;// 获取物体当前位置信息Vector3 position = transform.position;Debug.Log(" ** 物体的位置" + position.x + ' ' + position.y + ' ' + position.z);}// Update is called once per framevoid Update(){}
}
本地坐标
    void Start(){ // 获取当前物体的transform组件Transform transform = this.gameObject.transform;// 获取物体当前位置信息Vector3 position = transform.localPosition;Debug.Log(" ** 本地物体的位置" + position.ToString("F4"));}

注意:本地坐标在移动父节点时,子节点的本地坐标是不变的!

播放模式

播放模式所有窗口中的操作不会影响调试模式

帧更新

基本概念:

Frame:一个游戏帧

FrameRate:帧率、刷新率

FPS(Frames per seconds):每秒钟刷新多少帧

帧观察的方法

Time.time,游戏时间

Time.deltaTime,距离上次更新的时间差

unity中更新帧的速度特别快,而且不固定

// Update is called once per framevoid Update(){// Time.time 获取当前游戏的时间
//        Debug.Log(" ** update methoed has going, time = " + Time.time);Debug.Log(" ** update methoed has going, time = " + Time.deltaTime);}

解释:为什么帧的更新是不固定的

游戏引擎属于一个程序,一个程序运行在一个操作系统上面,由于不是独占式地调用,所以游戏引擎无法持续地运行。CPU的资源是一定的

unity设置近似帧率 (在开始的时候设置)

Application.targetFrameRate = 60;

物体运动

让gameObject动起来
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class moveByx : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){Application.targetFrameRate = 60;}// Update is called once per framevoid Update(){Debug.Log(" ** 更新时间差 = " + Time.deltaTime);Vector3 position = this.transform.localPosition;position.x += 0.001f;this.gameObject.transform.position = position;}
}

这显示的效果是变速运动,只是每次运动的间隔是0.01米。

让gameObject匀速运动
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class moveByx : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){Application.targetFrameRate = 60;}// Update is called once per framevoid Update(){Debug.Log(" ** 更新时间差 = " + Time.deltaTime);Vector3 position = this.transform.localPosition;float speed = 3;// 算匀速距离 = 速度 * 过去的时间float distance = speed * Time.deltaTime; position.x += distance;this.gameObject.transform.position = position;}
}
物体运动优化
void Update(){float speed = 1;float distance = speed * Time.deltaTime;/*Vector3 positiion = this.transform.localPosition;positiion.z += distance;this.transform.localPosition = positiion;*/this.transform.Translate(0, 0, -distance);}
坐标系运动(重要)
void Update(){float speed = 1;float distance = speed * Time.deltaTime;// 相对于世界坐标系运动this.transform.Translate(distance, 0, distance, Space.World);// 相对于物体自身坐标系运动this.transform.Translate(distance, 0, distance, Space.Self);}
转向并移动
public class Logic : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){GameObject flag = GameObject.Find("红旗");this.transform.LookAt(flag.transform);}// Update is called once per framevoid Update(){float speed = 1;float distance = speed * Time.deltaTime;/*// 相对于世界坐标系运动this.transform.Translate(distance, 0, distance, Space.World);*/// 相对于物体自身坐标系运动this.transform.Translate(distance, 0, distance, Space.Self);}
}

物体旋转

注意:旋转不使用rotation实现,rotation主要是在unity内部调用,开发人员实现旋转主要是由欧拉角实现。

设置物体转动
void Start()
{// 欧拉角 在y轴方向上旋转45度transform.localEulerAngles = new Vector3(0, 45, 0);
}
实现动态旋转
void Update()
{// 设置角速度float rotateSpeed = 30;// 设置帧率为60Application.targetFrameRate = 60;// 获取当前转动角度Vector3 angles = this.transform.localEulerAngles;// 设置角度增量angles.y += rotateSpeed * Time.deltaTime;// 为物体赋值新角度this.transform.localEulerAngles = angles;
}
相对旋转(重要)
void Update()
{// 简化上面的代码为一行代码this.transform.Rotate(0, rotateSpeed * Time.deltaTime, 0, Space.Self);
}
自转与公转

自转:前面的旋转实现的就是自转

公转:当父物体转动时,带着子物体一起转动

void Update()
{Transform parent = this.transform.parent;float rotateSpeed = 30;Application.targetFrameRate = 60;parent.Rotate(0, rotateSpeed * Time.deltaTime, 0, Space.Self);
}
分析公转模型关系

地月系统:空物体

地球:和空物体重合

卫星:和a1物体重合

所以两个物体都可以通过设置物体公转实现,而且设置公转的时候可以设置不同的角速度

脚本的运行
  1. 创建结点
    • GameObject node = new GameObject()
  2. 实例化组件
    • MeshRender comp = new MeshRender()
  3. 实例化脚本组件
    • SimpleLogic script1 = new SimpleLogic()
  4. 调用事件函数
    • 初始化函数
    • 帧更新函数
消息函数

所有的脚本一般都继承于MonoBehaviour

消息函数:事件函数,一些回调函数

常见的消息函数
函数名称函数描述
Awake第一阶段初始化,仅执行一次
Start第二阶段初始化,仅执行一次
Update帧更新,每帧调用一次
OnEnable每当组件启用时调用
Ondisable每当组件禁用时调用

Awake()与Start()的区别与联系

  • Awake()在Start()之后运行

  • 取消脚本的调用之后Awake()依然会被调用

  • 只会执行一次

OnEnable()与OnDisable()的区别与联系

  • OnEnable()在脚本调用时使用
  • OnDisable()在脚本取消调用时使用
  • 可执行多次
消息函数的顺序

Awake() --> OnEnable() --> Start()

脚本执行顺序

第一阶段:所有脚本的Awake()函数

第二阶段:所有脚本的Start()函数

第三阶段:所有脚本的Update()函数

脚本执行顺序(脚本的优先级)可以在Unity中设置,但是其实没有必要

主控脚本

设置游戏的全局设置

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class MainLogic : MonoBehaviour
{public void Awake(){Application.targetFrameRate = 60;}// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){}
}

这个脚本可以适当地调高优先级

脚本参数
脚本参数用法
  1. 参数必须为public,才可以在检查器中显示
  2. 参数的名称,即变量名
    • rotateSpeed --> Rotate Speed
  3. 参数的默认值,即变量的默认值
    • 可以Reset菜单重置
  4. 参数的工具提示,可以用[Tooltip()]指定
示例代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class RotateY : MonoBehaviour
{// 注解[ Tooltip("这个是y轴向的角速度")]public float rotateSpeed = 30f;// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){//float speed = 30f;this.transform.Rotate(0, rotateSpeed * Time.deltaTime, 0, Space.Self);}
}

作用:可以在unity中对参数重新进行赋值

脚本参数的赋值与最终取值示例

定义时:RotateY script = new RotateY()

unity参数赋值:script.rotateSpeed = 180f

脚本消息函数:script.Awake()

脚本消息函数:script.Start()

从上到下逐级覆盖

脚本参数类型

值类型与引用类型

public int intValue = 0;public float floatValue = 0.5f;public bool boolValue = true;public string stringValue = "我叫icyler";public Vector3 rotateSpeed2 = new Vector3(1,1,1);public Color color;

值类型的特点:

  • 本身是一个值,可直接赋值
  • 若未赋值,则默认为0
  • 不能为null
public GameObject target;

引用类型特点:

  • 可以成为引用数据类型的数据:结点、组件、资源、数组类型
  • 需要对其进行赋值,无论是unity还是在C#代码中,否则会显示空指针异常

AudioSource组件

脚本中使用API播放音乐
  1. 获取AudioSource组件
    • AudioSource audio = this.GetComponent<AoudioSource>();
  2. 播放
    • audio.Play();
代码实现
void Update()
{// 设置鼠标点击事件if(Input.GetMouseButtonDown( 0)){playMusic();}
}void playMusic()
{// 获取AudioSource组件AudioSource audio = this.GetComponent<AudioSource>();if ( audio.isPlaying){audio.Stop();}else{audio.Play();}
}

事物逻辑:

在刷新的时候判断是否有鼠标点击事件,如果有执行鼠标点击之后的逻辑(播放音乐 ;播放音乐需要调用相关的组件,这里顺便回顾组件的调用方式)。

介绍AudioSource插件上面的组件
属性描述
Mute静音
Loop是否循环播放
volume0~1 音量大小
代码实现
// 获取AudioSource组件
AudioSource audio = this.GetComponent<AudioSource>();
// 设置静音
audio.mute = true;
// 设置循环播放
audio.loop = true;
引用别的物体的组件

可以选择直接引用模型的结点或者引用墨香

示例(不常用)
// 游戏主控节点引用背景音乐结点
public GameObject bgmNode;// Start is called before the first frame update
void Start()
{AudioSource audio = bgmNode.GetComponent<AudioSource>();audio.Play();
}
示例(常用)
// 引用模型下的组件
public AudioSource bgm;

获取脚本组件

通过游戏主控节点引用脚本组件
public GameObject gameNode;// Update is called once per frame
void Update()
{if(Input.GetMouseButtonDown(0)){}
}void DoWork()
{FanLogic fan = gameNode.GetComponent<FanLogic>();fan.rotateSpeed = 180;
}

记得最后在unity中修改GameObject模型引用

通过游戏组件引用脚本组件
public FanLogic fanLogic;// Update is called once per frame
void Update()
{if(Input.GetMouseButtonDown(0)){DoWork();}
}void DoWork()
{fanLogic.rotateSpeed = 180;
}

记得最后在unity中修改fanLogic组件引用

获取游戏物体

回顾之前的方法:

  1. 按名称、路径获取(效率低,而且不能自适应组件名的改变)(不推荐)
    • GameObject node = GameObject.Find(“种子”);
  2. 引用获取游戏节点(需要拖动获取节点,不容易出错)(推荐)
    • public GameObject wingNode;

获取父级和子级节点

获取父级方法:使用Transform。

void Start()
{Transform parent = this.transform.parent;GameObject parentNode = this.transform.parent.gameObject;Debug.Log(" * 父级:" + parent.name);
}

获取子级方法:

  1. foreach遍历
// 获取每一个子节点的名字
void Start()
{Transform parent = this.transform.parent;GameObject parentNode = this.transform.parent.gameObject;Debug.Log(" * 父级:" + parent.name);
}
  1. GetChild(),按索引获取子节点
void Start()
{Transform aa = this.transform.GetChild(0);Debug.Log(" * 子物体" + aa.name);
}
  1. Find(),按节点名字获取子节点
Transform cube = this.transform.Find("2.0");
if (cube != null)
{Debug.Log(" * 找到子物体" + cube.name);
}
else
{Debug.Log("没有找到");
}

注意:也可以获取二级子节点,需要用/分开

通过脚本设置音频(不通过组件)

public AudioClip audioTest;void Update()
{// 获取播放音乐的组件AudioSource audioSource = GetComponent<AudioSource>();// 点击A键并且组件没有播放音乐时播放音乐if (Input.GetKeyDown(KeyCode.A) && !audioSource.isPlaying){;// 播放音乐audioSource.PlayOneShot(audioTest);}if (Input.GetKeyDown(KeyCode.S) && audioSource.isPlaying){// 停止播放音乐audioSource.Stop();}
}

定时器调用

简单延时——Invoke和InvokeRepeat用法

void start()
{// 延时1s后执行this.Invoke("DoSomething", 1);// 之后延迟2s执行一次// 参数:1. 函数名   2. 开始时静止时间   3. 间隔时间this.InvokeRepeating("DoSomething", 1, 2);
}private void DoSomething()
{Debug.Log(" * doing something ...");
}
取消定时器
CancelInvoke("reverseSpeed");

向量

获取向量长度
// 创建一个分量分别位3 0 4 的向量
Vector3 v = new Vector3(3, 0, 4);
// 获取变量长度 (开根了,float类型)
float len = v.magnitude;
// 打印输出
Debug.Log("magnitude值为:" + len);
单位向量

向量长度为1的向量

标准化向量
Vector3 v1 = new Vector3(2, 2, 0);
Vector3 v2 = v1.normalized;Debug.Log("标准化的值为:" + v2.ToString("f6"));
向量相关的常量unity定义
Vector3.zero;   // (0,0,0)
Vector3.up;     // (0,1,0)
Vector3.right;  // (1,0,0)
Vector3.forward;// (0,0,1)

向量的运算

向量的加法
Vector3 a = new Vector3(1, 3, 0);
Vector3 b = new Vector3(4, 1, 3);Vector3 c = a + b;Debug.Log("标准化的值为:" + c.ToString("f6"));
向量的减法
Vector3 a = new Vector3(1, 3, 0);
Vector3 b = new Vector3(4, 1, 3);Vector3 c = a - b;Debug.Log("标准化的值为:" + c.ToString("f6"));
向量的乘法
Vector3 a = new Vector3(1, 3, 0);
Vector3 b = new Vector3(4, 1, 3);
// 标量 * 向量
b = a * 2
// 点积
Vector3 c = Vector3.Dot(a,b);
// 差积
Vector3 c = Vector3.Cross(a,b);
向量的赋值

因为Vetor类型为值类型,所有不能将其值赋值为null

public Vector3 a = new Vector3(1, 3, 0);
public Vector3 b;
b = a;

向量测距

  • 求两个节点方向向量
  • 用Vector.magnitude求距离
// 示例
void Start()
{GameObject target = GameObject.Find("your gameobject name");Vector3 p1 = this.transform.position;Vector3 p2 = this.transform.position;Vector3 direction = p2 - p1;flat distance = direction.magnitude;
}// 简化写法 Distance
void Start()
{GameObject target = GameObject.Find("your gameobject name");Vector3 p1 = this.transform.position;Vector3 p2 = this.transform.position;float distance = Vector3.Distance(p2,p1);
}

细节处理:仔细观察两物体之间的距离需要两个物体的中心点都在底面中心或者是两个物体的中心点都在轴心上面,否则不好求中心点的坐标。

* 示例:用向量指定物体移动

这样写的好处:可以控制物体移动的方向而不需要重新修改脚本。这样可以有效减少测试时间。

public Vector3 speed;
void Update()
{Vector3 delta = speed * Time.deltaTime;this.transform.Translate(delta, Space.Self);
}

预制体(Prefabs)

概念:预先制作的模型物体,就是3D模型

预制体的创建

  1. 先制作好一个样本节点
  2. 做好以后,直接拖到Assets窗口(可以新建一个Prefabs文件夹,方便管理)
  3. 原始的节点不需要可以删除

预制体的作用

预制体相当于一个框架(模板),可以批量制作多个相同物体。

预制体的编辑

  • 方式一
    • 双击Prefeb实例,进入单独编辑模式
    • 编辑节点和组件
    • 退出,完成编辑(发现所有通过预制体生成的实例都发生了相对应的改变)
  • 方式二
    • 与上面的编辑方式的区别,可以看见其他的物体但是无法对其进行编辑
  • 方式三
    • 对实例进行修改然后在实例中点击Overrides

动态创建节点

动态创建实例

通过点击在固定位置创建实例

// 获取预制体模型
public GameObject bulletPrefab;void Update()
{if(Input.GetMouseButtonDown){TestFire();}private void TestFire(){GameObject node = object.Instantiate(bulletPrefab ,null);node.transform.position = Vector3.zero;node.transform.localEulerAngles = Vector3.zero;}
}
动态初始化实例
// 获取预制体模型
public GameObject bulletPrefab;
// 子弹目录
public Transform bulletFolder;
// 弹药出生点位置
public Transform firePoint;
// 弹药出生点方向
public Transform cannon;
void Update()
{if(Input.GetMouseButtonDown){TestFire();}private void TestFire(){// 将新创建的节点放在一个目录下,统一管理GameObject node = object.Instantiate(bulletPrefab ,bulletFolder);node.transform.position = this.firePoint.position;  // Vector3.zero;// node.transform.localEulerAngles = Vector3.zero;node.transform.eulerAngles = this.cannon.eulerAngles;}
}
动态销毁实例(在预制体内定义)

注意:使用的时候需要再在脚本中为maxDistance赋值

public float speed;
public float maxDistance;void Start()
{float lifeTime = 1;if(speed > 0){lifeTime = maxDistance / speed;}Invoke("SelfDestroy",lifeTime);
}void Update()
{this.transform.Translate(0,0,Space.Self);
}private void SelfDestroy()
{Object.Destroy(this.GameObject);
}
实例的销毁

运行时调试

运行时可以对游戏场景中运行的组件进行调整

例如:

  • 拖动组件的x、y、z坐标轴
  • 修改组件的坐标值

注意:

调试完成的操作不能被保存

调试时参数的保存

play Mode下,组件 Copy Component

edit Mode下,组件 Plaste Component Values

unity的运作方式:单线程

除非添加了一些网络逻辑,否则都不需要添加线程,故而也不需要考虑线程的并发、互斥等概念

练习项目

练习1:自定义音乐盒

  1. Assets目录下music目录下放入多首歌曲
  2. 在一个场景中创建一个空节点(create empty)重命名为音乐盒
  3. 为其添加AudioSource组件并取消勾取里面的(Play on Awake)
  4. 为其添加脚本(自命名)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class MusicBox : MonoBehaviour
{// 定义一个数组存放音乐public AudioClip[] songs;// Start is called before the first frame updatevoid Start(){// 友好的判断音乐盒是否能够使用if (songs == null || songs.Length == 0){Debug.Log("* 请检查音乐盒内歌曲");}}public void NextSong(){// 随机函数int index = Random.Range(0, songs.Length);// 获取歌曲名字AudioClip clip = this.songs[index];// 获取AudioSource组件AudioSource audio = GetComponent<AudioSource>();// 将对应数组值传给音乐播放组件audio.clip = this.songs[index];// 最后要播放音乐audio.Play();// 顺便可以打印一下音乐播放信息Debug.Log("播放第" + (index + 1) + "首歌曲,歌曲名叫:" + clip.name);}
}

练习2:变色小球

  1. 同上Assets目录下material目录下放入多个材质
  2. 在一个场景中创建小球
  3. 为其添加脚本(自命名)
public class color : MonoBehaviour
{// 材料盒public Material []colors;// Update is called once per framevoid Update(){// 鼠标点击事件if(Input.GetMouseButton(0)){// 调用变换颜色方法ChangeColor();}}// 定义变换颜色方法public void ChangeColor(){// 生成随机数int index = Random.Range(0, colors.Length);// 获取随机颜色Material selected = this.colors[index];// 获取当前组件MeshRenderer rd = GetComponent<MeshRenderer>();// 为当前组件设置材质rd.material = selected;}
}

练习3:往复运动的小球

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class timer : MonoBehaviour
{float speed = 1.5f;// Start is called before the first frame updatevoid Start(){// 之后延迟2s执行一次// 参数:1. 函数名   2. 开始时静止时间   3. 间隔时间this.InvokeRepeating("reverseSpeed", 2, 2);}// Update is called once per framevoid Update(){this.transform.Translate(0, speed * Time.deltaTime, 0, Space.Self);}public void reverseSpeed(){this.speed = -this.speed;}
}

练习4:闪烁灯

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class lamp : MonoBehaviour
{public Material[] colors;int index = 0;// Start is called before the first frame updatevoid Start(){changeColor();}// Update is called once per framevoid Update(){}public void changeColor(){// 设置材质Material color = this.colors[index];MeshRenderer renderer = GetComponent<MeshRenderer>();renderer.material = color;Debug.Log("* change ->" + index + ",time = " + Time.time);if(index == 0){Invoke("changeColor", 4);}else if(index == 1){Invoke("changeColor", 4);}else if (index == 2){Invoke("changeColor", 4);}index++;if (index >= 3) index = 0;}
}

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

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

相关文章

顶顶顶顶顶顶顶顶顶顶顶顶

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和技术。关…

【电子通识】为什么用双绞线?双绞线抗干扰的原理是什么?

使用双绞线最大的理由是抗干扰。不仅可以防止别人干扰,也可以防止自己干扰别人。这与EMC中的EMS和EMI相对应(参考【EMC专题】电磁兼容--基本概念)。 双绞线是由一对带有绝缘层的铜线(绝缘层使两根线中的金属导体不会因为互碰而导致短路)以螺旋的方式缠绕在一起所构成的。通…

ElementUI从unpkg.com完整下载到本地的方法 - 解决unpkg.com不稳定的问题 - 自建镜像站 - 不想打包只想cdn一下

方法 方法1&#xff09;随便弄个文件夹&#xff0c;根据官网npm方法下载包&#xff0c;提取即可 npm i element-ui -S cd /node_modules/element-ui/ ls src 安装npm方法&#xff1a;https://nodejs.org/en 方法2&#xff09;不推荐 - 在github中搜索对应的库zip包&#xff0…

【网络原理】HTTP 协议的基本格式和 fiddler 抓包工具的用法

系列文章目录 【网络通信基础】网络中的常见基本概念 【网络编程】网络编程中的基本概念及Java实现UDP、TCP客户端服务器程序&#xff08;万字博文&#xff09; 【网络原理】UDP协议的报文结构 及 校验和字段的错误检测机制&#xff08;CRC算法、MD5算法&#xff09; 【网络…

PG实例连接访问控制

实例访问控制可以控制来自于不同主机&#xff0c;不同用户是否允许访问指定的数据库&#xff0c;以及验证方式。 与oracle中的连接管理器的功能相同&#xff0c;之前有写过一篇oracleCMAN连接管理器的配置实操&#xff1a; 配置oracle连接管理器&#xff08;cman&#xff09;…

深度学习每周学习总结P7(咖啡豆识别)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 –来自百度网盘超级会员V5的分享 数据链接 提取码&#xff1a;7zt2 –来自百度网盘超级会员V5的分享 目录 0. 总结1. 数据导入及处理部分…

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《电-氢-混氢天然气耦合的城市综合能源系统低碳优化调度》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

Java | Leetcode Java题解之第68题文本左右对齐

题目&#xff1a; 题解&#xff1a; class Solution {private String line(List<String> list,int maxWidth,int totalLength,boolean isLast){StringBuilder sb new StringBuilder();sb.append(list.get(0));if(list.size() 1){String ap " ".repeat(maxW…

二维数组的鞍点(C语言)

一、鞍点解释&#xff1b; 鞍点就是该位置上的元素在该行上最大、在该列上最小&#xff1b; 二、N-S流程图&#xff1b; 三、运行结果&#xff1b; 四、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff…

定制开发AI名片商城AI导购系统:引领营销自动化的新时代

在数字营销日新月异的今天&#xff0c;一个革命性的工具——定制开发AI名片商城AI导购系统&#xff0c;正逐渐崭露头角&#xff0c;成为企业私域运营中的得力助手。它不仅仅是一个营销工具&#xff0c;更是一个拥有强大营销自动化能力和先进算法技术的在线助理&#xff0c;为企…

【neteq】tgcall的调用

G:\CDN\P2P-DEV\Libraries\tg_owt\src\call\call.cc基本是按照原生webrtc的来的:G:\CDN\P2P-DEV\tdesktop-offical\Telegram\ThirdParty\tgcalls\tgcalls\group\GroupInstanceCustomImpl.cpptg对neteq的使用 worker 线程创建call Call的config需要neteqfactory Call::CreateAu…

[1702]java旅游资源网上填报系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java旅游资源网上填报系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql…

模式识别作业:颜色算子的三种阈值分割算法

一、引言&#xff1a; 在图像处理中&#xff0c;我们往往需要提取图像的一些关键信息&#xff0c;比如本篇文章的内容——提取颜色&#xff0c;然而当我们需要提取某一种颜色时&#xff0c;无论图像余下的部分如何“丰富多彩”&#xff0c;他们都不再重要&#xff0c;需要被忽…

如何使用SSH密钥克隆仓库

1.创建SSH Key 在用户目录下查看有没有.ssh目录。如果有且该.ssh目录下有id_rsa&#xff08;私钥&#xff09;&#xff0c;和id_rse_pub(公钥)这俩文件&#xff0c;那么这一步就可以跳过。否则使用以下指令创建SSH Key ssh-keygen -t rsa -C "xxxqq.com" "xx…

8.k8s中网络资源service

目录 一、service资源概述 二、service资源类型 1.ClusterIP类型 2.service的nodeport类型 3.service的loadbalancer类型&#xff08;了解即可&#xff09; 4.service的externalname类型&#xff08;了解即可&#xff09; 三、nodeport的端口范围设置和svc的endpoint列表 1.修…

AJAX概述和基本使用

01 【AJAX概述和基本使用】 1.AJAX简介 AJAX 全称为Asynchronous JavaScript And XML&#xff0c;就是异步的JS 和XML 通过AJAX 可以在浏览器中向服务器发送异步请求&#xff0c;最大的优势&#xff1a;无刷新获取数据 AJAX 不是新的编程语言&#xff0c;而是一种将现有的标准…

刷代码随想录有感(53):合并二叉树

题干&#xff1a; 代码&#xff08;递归实现&#xff09;&#xff1a; TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {//前序好理解&#xff0c;直接将树覆盖到另一个上面if(root1 NULL)return root2;//当前遍历节点为空的话就让另一个的值覆盖过来if(root2 NUL…

对命令模式的理解

目录 一、场景1、文本编辑器并不是一个好的例子&#xff0c;设备控制器才是2、设备控制器的demo 二、不用命令模式1、代码2、问题 三、使用命令模式1、代码2、当需求变化时2.1 新增代码2.2 优点 四、进一步思考1、省略对Command的建模可以吗&#xff1f;2、命令模式的价值 一、…

GDPU unity游戏开发 碰撞器与触发器

砰砰叫&#xff0c;谁动了她的奶酪让你的小鹿乱撞了。基于此&#xff0c;亦即碰撞与触发的过程。 碰撞器与触发器的区别 通俗点讲&#xff0c;碰撞器检测碰撞&#xff0c;触发器检测触发&#xff0c;讲了跟没讲似的。碰撞器是用来检测碰撞事件的&#xff0c;在unity中&#xff…

蓝桥杯练习系统(算法训练)ALGO-949 勇士和地雷阵

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 勇士们不小心进入了敌人的地雷阵&#xff08;用n行n列的矩阵表示&#xff0c;*表示某个位置埋有地雷&#xff0c;-表示某个…