3D数学复习
using System.Collections; using System.Collections.Generic; using UnityEngine; public class w07d1 : MonoBehaviour { public Quaternion result1; public Quaternion result2; public Quaternion result3; // 什么是单位四元数? // [0, 0, 0, 1] 表示无旋转 // [n.x * sin<theta/2>, n.y * sin<theta/2>, n.z * sin<theta/2>, cos<theta/2>] 绕y轴旋转0度 [0, 0, 0, 1] 绕y轴旋转360度 [0, 0, 0, -1] // 什么是标准四元数? // 模长为1的四元数 // 模长 = Mathf.Sqrt(x*x + y*y + z*z * w*w) // 什么是共轭四元数? // 虚数部分取负 // 四元数 * 共轭四元数 = 单位四元数 // 什么是四元数的逆? // q^-1 = q^* / |q| 如果q是标准四元数 q^-1 = q^* // 如果一个 四元数 * 向量 = 向量 (模长一样,方向不一样,相当于旋转一个向量) void Start () { // 绕 (1, 1, 0)轴 旋转45度 result1 = Quaternion.AngleAxis(45, new Vector3(1, 1, 0)); // 绕 (2, 2, 0)轴 旋转45度 result2 = Quaternion.AngleAxis(45, new Vector3(2, 2, 0)); // 对轴 标准化 Quaternion ge = new Quaternion(-result1.x, -result1.y, -result1.z, result1.w); result3 = result1 * ge; Quaternion q = Quaternion.AngleAxis(45, Vector3.up); Vector3 v = new Vector3(1, 0, 1); Debug.DrawLine(Vector3.zero, v, Color.green, 1000); v = q * v; Debug.DrawLine(Vector3.zero, v, Color.red, 1000); } }
RotateAround
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MyRotateAroundTest : MonoBehaviour { public Transform target; public float rotSpeed = 1; void Start () { } void Update () { MyRotateAround(target.position, target.up, rotSpeed * Time.deltaTime); } void MyRotateAround(Vector3 pos, Vector3 axis, float angle) { Quaternion q = Quaternion.AngleAxis(angle, axis); Vector3 dir = transform.position - pos; Vector3 projectV = (Vector3.Dot(axis, dir) / axis.magnitude) * axis.normalized; Vector3 n = dir - projectV; Vector3 newN = q * n; Vector3 newPos = pos + projectV + newN; transform.position = newPos; transform.rotation *= q; } }
摄像机
Clear Flags(清除标志):摄像机剔除标志选择
----Skybox(天空盒):增加显卡渲染负担,2D游戏看不到天空的可以选择 Solid Color纯色
----Solid Color(纯色):
----Depth only(只深度):
----Don't Clear(不清除):会留下残影,此很少用
BackGround:背景色(当选为Solid Color的时候,背景颜色是可选的)
Culling Mask(剔除遮罩):通过层级来筛选这个Camera要渲染的游戏物体
1、给Plane和Sphere添加层级 2、辅摄像机添加Depth only,Depth改为1,比主摄像机Depth0要大 3、主摄像机剔除小球,辅摄像机只保留小球
Projection:决定了此Camera的投影方式
----Perspective(透视投影,近大远小):发散形视角
--------Field of View(视野角度大小):可以做运动相机的鱼眼镜头
----Orthographic(正交投影,没有近大远小):非发散形视角,以矩形平行出去,2D游戏,暗黑2
--------Size(视口大小):调整正交投影下视口大小的,通过分辨率运算得出
1方块=1米=100像素 Size = 屏幕分辨率 / 100(unity默认一个方格的像素) / 2(屏幕高度的一半) 正好可以把背景投射完整
Clipping Planes(剔除裁剪平面):调整摄像机的近裁面和远裁面,只有在近裁面和远裁面之间的游戏物体,才会被渲染显示
----Near:近裁面(最小值0.01)
----Far:远裁面
Viewpoint Rect(视口矩形框):调整摄像机渲染的游戏画面在整个游戏屏幕中的比例尺寸,以屏幕左下角为基准点
作用:分屏游戏,小地图(耗费性能,用UI等比例投放)
----X、Y:游戏画面相对于屏幕左下角的位置
----W、H:游戏画面占屏幕的宽、高
Depth(深度):摄像机深度越大,越后渲染,后渲染的会把先渲染的覆盖掉
使用:
1、渲染顺序
2、CS枪支单独摄像机渲染,再叠加到人物的主摄像机
渲染次序,先渲染场景(-1),后渲染枪支(0),空白部分用Clear Flags - Depth only渲染
Rendering path(渲染路径):预设渲染路径、延时渲染路径,定点照明渲染路径
Target Texture(目标贴图):摄像机渲染出来的画面可以投射到Game视图中,也可以投射到一张纹理贴图上
作用:电脑、赛车游戏的后视镜
Occlusion Culing():渲染范围剔除
Allow HDR(高动态贴图):需要延时渲染路径
Allow MSAA(抗锯齿):性能消耗大,不推荐使用,市面流行官方免费插件TSAA,需自行导入
Allow Dynamic Reso:
摄像机跟随功能
Unity2017增加智能相机
VS2015的ReSharper插件安装
强大的智能提示
补充内容-查找篇:
标签
GameObject.Find();
GameObject.FindGameObjectsWithTag();//查找所有带标签的游戏物体
GameObject.FindGameObjectWithTag();
GameObject.CompareTag();
层级
前8个层级是Unity默认的,无法修改
碰撞层级矩阵取消,可以取消敌人之间的碰撞
更换天空球的材质
赛车游戏
车轮碰撞器
第三人称视角:人
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ThirdPersonalCameraControl : MonoBehaviour { public float moveSpeed = 5; public float rotateSpeed = 60; private float keyboard_h; private float keyboard_v; private Camera camera; // Use this for initialization void Start () { camera = Camera.main; } // Update is called once per frame void Update () { keyboard_h = Input.GetAxis("Horizontal"); keyboard_v = Input.GetAxis("Vertical"); PlayerMove(); } void PlayerMove() { Vector3 cameraForward = Vector3.ProjectOnPlane(camera.transform.forward,Vector3.up).normalized; Vector3 cameraRight = Vector3.ProjectOnPlane(camera.transform.right, Vector3.up).normalized; transform.Translate(cameraForward * Time.deltaTime * moveSpeed * keyboard_v); transform.Translate(cameraRight * Time.deltaTime * moveSpeed * keyboard_h); } }
第三人称视角:摄像机
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ThirdCameraControl : MonoBehaviour { public Transform player; public float rotateSpeed = 60; private float mouse_h; private float mouse_v; private float mouseWheel; private Vector3 player2CameraVector; // Use this for initialization void Start () { player2CameraVector = transform.position - player.position; } // Update is called once per frame void Update () { mouse_h = Input.GetAxis("Mouse X") * rotateSpeed; mouse_v = -Input.GetAxis("Mouse Y") * rotateSpeed; mouseWheel = Input.GetAxis("Mouse ScrollWheel") * rotateSpeed; PlayeRotate(); MouseScrollWheel(); } void PlayeRotate() { //一个控制人物(左右转向,放人物身上) transform.Rotate(Vector3.up * Time.deltaTime * rotateSpeed * mouse_h); Vector3 eulurVector3 = new Vector3(mouse_v, mouse_h, 0); Quaternion targetQ = Quaternion.Euler(eulurVector3); Vector3 newVector3 = targetQ * player2CameraVector; transform.position = player.position + newVector3; transform.LookAt(player); //思考题:上下无法移动 } void MouseScrollWheel() { player2CameraVector = player2CameraVector + player2CameraVector.normalized * mouseWheel; Vector3 eulurVector3 = new Vector3(mouse_v, mouse_h, 0); Quaternion targetQ = Quaternion.Euler(eulurVector3); Vector3 newVector3 = targetQ * player2CameraVector; transform.position = player.position + newVector3; transform.LookAt(player); //限制 } }
第一人称视角:人
using System.Collections; using System.Collections.Generic; using UnityEngine; public class FirstPersonalCameraControl : MonoBehaviour { public float moveSpeed = 5; public float rotateSpeed = 60; private float keyboard_h; private float keyboard_v; private float mouse_h; private float mouse_v; // Use this for initialization void Start () { } // Update is called once per frame void Update () { keyboard_h = Input.GetAxis("Horizontal"); keyboard_v = Input.GetAxis("Vertical"); mouse_h = Input.GetAxis("Mouse X"); mouse_v = Input.GetAxis("Mouse Y"); PlayerMove(); PlayeRotate(); } void PlayerMove() { //写两个代码:一个控制人物(左右转向,放人物身上),一个控制摄像机(上下转向,放摄像机身上) transform.Translate(Vector3.forward * Time.deltaTime * moveSpeed * keyboard_v); transform.Translate(Vector3.right * Time.deltaTime * moveSpeed * keyboard_h); } void PlayeRotate() { //一个控制人物(左右转向,放人物身上) transform.Rotate(Vector3.up * Time.deltaTime * rotateSpeed * mouse_h); } }
第一人称视角:摄像机
using System.Collections; using System.Collections.Generic; using UnityEngine; public class FirstCameraControl : MonoBehaviour { //上下转动(180)要比左右转动(360)角度小 public float rotateSpeed = 60; private float mouse_v; // Use this for initialization void Start () { } // Update is called once per frame void Update () { mouse_v = Input.GetAxis("Mouse Y"); PlayeRotate(); } void PlayeRotate() { //一个控制摄像机(上下转动,放摄像机身上) transform.Rotate(Vector3.right * Time.deltaTime * rotateSpeed * -mouse_v); //限制摄像机上下转动幅度 } }
汽车
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CarMove : MonoBehaviour { public float moveSpeed = 5; public float rotateSpeed = 30; private float keyboard_h; private float keyboard_v; // Use this for initialization void Start() { } // Update is called once per frame void Update() { keyboard_h = Input.GetAxis("Horizontal"); keyboard_v = Input.GetAxis("Vertical"); transform.Translate(Vector3.forward * Time.deltaTime * moveSpeed * keyboard_v); transform.Rotate(Vector3.up * Time.deltaTime * rotateSpeed * keyboard_h); } }
摄像机
SmoothDamp,平滑阻尼,从固定的时间内到达某个位置,可用于摄像机跟随
velocity是Vector3类的结构体,不能直接对外传值,只能用ref传引用的地址,如果有多个物体伴随移动,可以用velocity的速度去控制
ref velocity,返回平滑阻尼的当前帧的速度(在Vector3各方向上的速度)
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CarCameraController : MonoBehaviour { public Transform car; public Transform lookTrans; public float followTime = 0.5f; private Vector3 currentVelocity; // Use this for initialization void Start() { } // Update is called once per frame void Update() { transform.position = Vector3.SmoothDamp(transform.position, car.position, ref currentVelocity, followTime); Vector3 dir = lookTrans.position - transform.position; Quaternion targetQuat = Quaternion.LookRotation(dir); transform.rotation = Quaternion.Slerp(transform.rotation, targetQuat, 0.1f); } }
对象池
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerControl : MonoBehaviour { public float moveSpeed = 1; Transform firePos; private void Awake() { firePos = transform.Find("firePos"); } void Update () { Vector3 moveDir = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0); transform.Translate(moveDir * Time.deltaTime * moveSpeed); if(Input.GetKeyDown(KeyCode.Space)) { // 通过实例化创建子弹 替换成对象池管理 //Instantiate(bulletPrefab, firePos.position, Quaternion.identity); PoolManager.Instance.Spawn(firePos.position, Quaternion.identity);//从对象池中取出游戏物体,要记得给对象赋于位置和方向 } } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class BossControl : MonoBehaviour { public int hp = 1000; void Start () { } void Update () { } private void OnTriggerEnter(Collider other) { if(other.gameObject.tag == "Bullet") { hp -= 10; // 子弹销毁 替换成对象池管理 //Destroy(other.gameObject); PoolManager.Instance.Push(other.gameObject); if(hp <= 0) { Destroy(this.gameObject); } } } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PoolManager : MonoBehaviour { private static PoolManager instance = null; public static PoolManager Instance { get { return instance; } } public GameObject bulletPrefab; public List<GameObject> bulletPool = new List<GameObject>(); // 列表来管理 // 创建的时候 从列表中取一个出来 激活 // 销毁的时候 把这个要销毁的游戏物体 失活, 放到列表中 // 把游戏物体 激活、失活 void Awake() { instance = this; } // 从对象池中取游戏物体 public GameObject Spawn(Vector3 pos, Quaternion qua) { GameObject go; if (bulletPool.Count == 0) { go = Instantiate(bulletPrefab, pos, qua); } else { go = bulletPool[bulletPool.Count - 1]; go.SetActive(true); bulletPool.RemoveAt(bulletPool.Count - 1); go.transform.position = pos; go.transform.rotation = qua; } //粒子特效的拖尾问题处理 //ParticleSystem ps = go.GetComponent<ParticleSystem>(); //if (ps) ps.Clear(); //ParticleSystem[] pses = go.GetComponentsInChildren<ParticleSystem>(); //foreach (var item in pses) //{ // item.Clear(); //} TrailRenderer tr = go.GetComponent<TrailRenderer>();//TrailRenderer的拖尾问题处理 tr.Clear(); //ps.Play(); //ps.Pause(); return go; } // 把游戏物体放回对象池 public void Push(GameObject go) { go.SetActive(false); bulletPool.Add(go); } }
Invoke,延时调用函数
using System.Collections; using System.Collections.Generic; using UnityEngine; public class BulletMove : MonoBehaviour { public float moveSpeed = 10; void Start () { // 销毁 替换成对象池管理 //Destroy(this.gameObject, 5f); Invoke("PushBack", 5f); // 延迟调用 } void Update () { transform.Translate(Vector3.forward * Time.deltaTime * moveSpeed); } void PushBack() { PoolManager.Instance.Push(this.gameObject); } }