赞
踩
重置界面布局: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模型(子 – > 父)
特点:
理解:
相对坐标:当模型成为某个模型的子节点的时候,子节点坐标从绝对坐标变成了相对坐标
主要用于两个不好确定父子关系的模型。可以将空物体作为两个模型的父节点,两个模型便可以无损地相对移动
坐标轴称谓:
y轴称为up,z轴称为forward,x轴称为right;一般来说:物体正面需要和z轴方向一致
操作基准点:前者以轴心点作为基准点,后者为几何中心点
默认为pivot
基本的组件
Mesh Renderer:网格渲染器
Light:光照显示
Mesh Filter:网格过滤器
组件映射了模型的功能,你需要一个节点具有什么样的功能,你就可以给组件挂载相对应的组件。
AudioSource:播放音乐,直接将对应音乐拖入AudioClip属性
Transform:变换组件
特点:
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 update void Start() { Debug.Log(" ** 我的第一个脚本"); } // Update is called once per frame void Update() { } }
前一个方法表示组件在加载的时候运行,后面一个方法在组件更新的时候运行
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(" ** 我的第一个脚本"); // 获取当前脚本所在物体本身 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 frame void 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 frame
void 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;
using System.Collections; using System.Collections.Generic; using UnityEngine; public class moveByx : MonoBehaviour { // Start is called before the first frame update void Start() { Application.targetFrameRate = 60; } // Update is called once per frame void Update() { Debug.Log(" ** 更新时间差 = " + Time.deltaTime); Vector3 position = this.transform.localPosition; position.x += 0.001f; this.gameObject.transform.position = position; } }
这显示的效果是变速运动,只是每次运动的间隔是0.01米。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class moveByx : MonoBehaviour { // Start is called before the first frame update void Start() { Application.targetFrameRate = 60; } // Update is called once per frame void 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 update void Start() { GameObject flag = GameObject.Find("红旗"); this.transform.LookAt(flag.transform); } // Update is called once per frame 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); } }
注意:旋转不使用rotation
实现,rotation
主要是在unity
内部调用,开发人员实现旋转主要是由欧拉角实现。
void Start()
{
// 欧拉角 在y轴方向上旋转45度
transform.localEulerAngles = new Vector3(0, 45, 0);
}
void Update()
{
// 设置角速度
float rotateSpeed = 30;
// 设置帧率为60
Application.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物体重合
所以两个物体都可以通过设置物体公转实现,而且设置公转的时候可以设置不同的角速度。
所有的脚本一般都继承于MonoBehaviour
消息函数:事件函数,一些回调函数
函数名称 | 函数描述 |
---|---|
Awake | 第一阶段初始化,仅执行一次 |
Start | 第二阶段初始化,仅执行一次 |
Update | 帧更新,每帧调用一次 |
OnEnable | 每当组件启用时调用 |
Ondisable | 每当组件禁用时调用 |
Awake()与Start()的区别与联系
Awake()在Start()之后运行
取消脚本的调用之后Awake()依然会被调用
只会执行一次
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 update void Start() { } // Update is called once per frame void Update() { } }
这个脚本可以适当地调高优先级
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 update void Start() {} // Update is called once per frame void 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;
值类型的特点:
public GameObject target;
引用类型特点:
AudioSource audio = this.GetComponent<AoudioSource>();
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(); } }
事物逻辑:
在刷新的时候判断是否有鼠标点击事件,如果有执行鼠标点击之后的逻辑(播放音乐 ;播放音乐需要调用相关的组件,这里顺便回顾组件的调用方式)。
属性 | 描述 |
---|---|
Mute | 静音 |
Loop | 是否循环播放 |
volume | 0~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组件引用
回顾之前的方法:
获取父级方法:使用Transform。
void Start()
{
Transform parent = this.transform.parent;
GameObject parentNode = this.transform.parent.gameObject;
Debug.Log(" * 父级:" + parent.name);
}
获取子级方法:
// 获取每一个子节点的名字
void Start()
{
Transform parent = this.transform.parent;
GameObject parentNode = this.transform.parent.gameObject;
Debug.Log(" * 父级:" + parent.name);
}
void Start()
{
Transform aa = this.transform.GetChild(0);
Debug.Log(" * 子物体" + aa.name);
}
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"));
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;
// 示例 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);
}
概念:预先制作的模型物体,就是3D模型
Prefabs
文件夹,方便管理)预制体相当于一个框架(模板),可以批量制作多个相同物体。
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); }
运行时可以对游戏场景中运行的组件进行调整
例如:
注意:
调试完成的操作不能被保存
在play Mode
下,组件 Copy Component
在edit Mode
下,组件 Plaste Component Values
除非添加了一些网络逻辑,否则都不需要添加线程,故而也不需要考虑线程的并发、互斥等概念
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("* 请检查音乐盒内歌曲"); } } 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); } }
public class color : MonoBehaviour { // 材料盒 public Material []colors; // Update is called once per frame void 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; } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class timer : MonoBehaviour { float speed = 1.5f; // Start is called before the first frame update void Start() { // 之后延迟2s执行一次 // 参数:1. 函数名 2. 开始时静止时间 3. 间隔时间 this.InvokeRepeating("reverseSpeed", 2, 2); } // Update is called once per frame void Update() { this.transform.Translate(0, speed * Time.deltaTime, 0, Space.Self); } public void reverseSpeed() { this.speed = -this.speed; } }
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 update void Start() { changeColor(); } // Update is called once per frame void 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; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。