unity官方案例精讲(第三章)--星际航行游戏Space Shooter
案例中实现的功能包括:
(1)键盘控制飞船的移动;
(2)发射子弹射击目标
(3)随机生成大量障碍物
(4)计分
(5)实现游戏对象的生命周期管理
导入的工程包中,包含着一个完整的 _scene---Main场景,创建一个全新场景,会在其中实现大部分功能
素材:
链接:https://pan.baidu.com/s/1-qFUYMjrvhfeOWThawJ-Hw
提取码:bhr8
一、场景准备
1、创建飞船对象:
(1)从project面板中Assets/models/vechicle_playerShip到Hierarchy视图,重命名player。reset它的Transform组件。
(2)添加Rigidbody组件:用途是通过脚本来为飞船添加作用力,此外不希望飞船受重力影响而下坠,取消Use Gravity选项。
(3)添加Mesh Collider组件:目的是使飞船能够和随机出现的障碍物发生随机碰撞,并在碰撞后触发销毁飞船和障碍物的事件。此时Mesh Collider组件的Mesh属性为模型vehicle_playerShip的网格,选中该网格模型,你可以看到在网格模型中包含了很多非常小的细小的三角面片。
由于上面的网格模型过于复杂,在进行碰撞检测时可能需要消耗大量的计算资源,降低游戏的执行效率,因此,没有必要进行这么精确的碰撞检测,可以通过建模建立一个简化的模型,减少不必要的碰撞计算。
为此选中同目录下的vehicle_playerShip_colloder,展开后选择对应的网格模型,将它拖动到Mesh Collider组件的Mesh属性上。还需要勾选Convex和Is Trigger选项框,设置为触发器。(Convex勾选复选框以启用凸面。如果启用,此网格碰撞器将与其他网格碰撞器碰撞。凸网格碰撞器限制为255个三角形)
其中勾选Convex(凸面)是unity新要求,否则运行会出现:Non-convex MeshCollider with non-kinematic Rigidbody is no longer supported since Unity 5.在前面添加刚体的时候,没有勾选Is Kinematic选项,unity5中不再支持非Kinematic刚体的非Convex网格碰撞体)
(4)添加飞船尾部火焰粒子效果:在project面板中,Assets/Perfabs/VFX/Engines目录下,将预制体engines_player拖动到Hierarchy视图的Player对象上,成为player的子对象。
2、设置摄像机的参数
摄像机的投影方式(projection)为Orthography(正交投影),size为10,Clear Flags为Solid Color,background为黑色,其他设置为保留值。
(Clear Flags: 每个摄影机在渲染其视图时存储的颜色和深度信息。屏幕中未绘制的部分为空,默认情况下将显示skybox。使用多个摄影机时,每个摄影机在缓冲区中存储自己的颜色和深度信息,在每个摄影机渲染时累积更多数据。当场景中的任何特定摄影机渲染其视图时,可以设置清除标志以清除缓冲区信息的不同集合。
skybox:这是默认设置。屏幕的任何空白部分都将显示当前相机的天空盒。如果当前摄影机没有设置“天空盒”(skybox)
solid color:屏幕的任何空白部分都将显示当前相机的背景色。
Depth only:如果要绘制玩家的枪而不让其在环境中被剪辑,请将一个摄影机设置为深度0以绘制环境,并将另一个摄影机设置为深度1以单独绘制武器。
Don't clear:此模式不清除颜色或深度缓冲区. 结果是,每个帧都会在下一帧上绘制,从而产生涂抹效果。这通常不用于游戏,而且更可能与自定义着色器一起使用
注意,在某些GPU(主要是移动GPU)上,如果不清除屏幕,可能会导致下一帧中未定义屏幕内容。在某些系统中,屏幕可以包含前一帧图像、实心黑屏幕或随机彩色像素
)
3、添加背景图片
(1)创建一个Quad面片,重命名为background,移除Mesh Collider组件,在Assets/Textures中选择tile_nubula_green_dff,将其拖动到background上,(此图片的尺寸是1024*2048,宽高比为1:2,为了防止图片被拉伸失真,在放大是需要遵循这个比例。)设置其Transform组件。纹理的shader设置为Unlit/Textures。
4、添加粒子背景效果
在真实的是空中应该是繁星点点,所以要添加粒子背景效果,让星空背景更贴近逼真
(1)在Assets/Prefabs/VFX/Starfield目录下,拖动预制体StarField到Hierarchy面板上,保留Transform组件属性的默认值,由于Y值为-5,高于background的(-10),所以不会被background挡住。
(2)展开StarField可以看到两个子对象,其中part_StarFied用于生成较大的粒子效果,另外一个生成较小的粒子效果。在子对象中,你会发现一个粒子系统组件(Particle System)
二、编写脚本代码
1、键盘控制飞船移动的操作
(1)在Assets中创建文件夹Scripts,在Scripts中创建PlayerController.cs脚本,由于需要处理刚体组件的物体特效,我们在此重载事件函数FixedUpdate,并且在其中添加如下代码:
void FixedUpdate()
{
//得到水平和竖直方向的输入
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical"); //利用上面得到的水平和竖直方向的输入创建一个vector3,作为刚体速度
Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
G
(2)绑定脚本到player对象,直接选中脚本,将其拖动到player上
(3)运行游戏,有三个问题:
- 飞船的移动速度过慢
- 没有对player做范围限制,飞船可以移动到屏幕外
- 左右移动飞船的时候,飞船没有侧翻效果
(4)解决上面问题,添加一个控制速度变量,创建一个public类型的变量speed
(5)添加限制对象运动范围的代码:
由于此场景飞机的活动范围是在xz平面上的,需要限制player的位置在有效的活动范围内,由background决定其xz的坐标值
- 在脚本中创建一个Boundary类用于管理飞船活动的范围,在PlayerController类中添加一个Boundary的实例。访问权限是public
public class Boundary
{
public float xMin, xMax, zMin, zMax;
}
public class Player_Control : MonoBehaviour
{
public float speed;//速度
public Boundary1 boundary;
- 要将一个物体限制在一个范围内,可以使用unity提供的Mathf.Clamp函数来实现:该函数若value的值小于min,则返回min;若value大于max,则返回max。于是可以在FixedUpdate中限定
static float Clamp(float value,float min,float max);
- 在player面板上,并没有看到boundary变量出现,需要为Boundary类添加可序列化的属性
[System.Serializable]
public class Boundary1
{
public float xMin, xMax, zMin, zMax;
}
- 运行游戏,寻找临界值。此时FixedUpdate函数的代码
void FixedUpdate()
{
//得到水平和竖直方向的输入
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical"); //利用上面得到的水平和竖直方向的输入创建一个vector3,作为刚体速度
Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
Rigidbody rb = GetComponent<Rigidbody>(); if(rb != null)
{
rb.velocity = movement * speed;
rb.position = new Vector3(Mathf.Clamp(rb.position.x, boundary1.xMin, boundary1.xMax), 0.0f,
Mathf.Clamp(rb.position.z, boundary1.zMin, boundary1.zMax));
}
}
(6)添加移动时旋转的效果
- 要是想飞船左右移动时,以一定的角度倾斜,需要在改变飞船位置的同时更新飞船的Rotation属性:在PlayerController类中添加一个倾斜系数tilt,设置默认值为4.0f.
- 在FixedUpdate函数中添加下面的语句
rb.rotation = Quaternion.Euler(0.0f, 0.0f, rb.velocity.x * -tilt);
- 函数Euler()是Quaternion的一个静态方法,接收绕XYZ轴的旋转角度为参数,并返回一个Quaternion对象。若飞船左右倾斜,则需要绕z轴旋转,往左移动的时候,x轴方向上速度为负值,而此时旋转角度(逆时针)应该为正值,所以需要乘以一个负数。
此时完整的PlayerController脚本代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine; [System.Serializable]
public class Boundary
{
public float xMin, xMax, zMin, zMax;
}
public class Player_Control : MonoBehaviour
{
public float speed;//速度
public Boundary boundary;
public float tilt = 4.0f; void FixedUpdate()
{
//得到水平和竖直方向的输入
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical"); //利用上面得到的水平和竖直方向的输入创建一个vector3,作为刚体速度
Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
Rigidbody rb = GetComponent<Rigidbody>(); if(rb != null)
{
rb.velocity = movement * speed;
rb.position = new Vector3(Mathf.Clamp(rb.position.x, boundary.xMin, boundary.xMax), 0.0f,
Mathf.Clamp(rb.position.z, boundary.zMin, boundary.zMax));
rb.rotation = Quaternion.Euler(0.0f, 0.0f, rb.velocity.x * -tilt);
}
}
}
三、实现射击行为
1、创建电光子弹
(1)新建一个空游戏对象,命名为Bolt,重置其Transform组件,为了防止Player遮挡Bolt,可暂时将player隐藏,然后为Bolt添加一个Rigidbody组件,并取消勾选Use Gravity。
(2)创建一个Quad,命名为VFX,将其设为Bolt的子对象,重置Transform组件,Rotation的属性值(90,0,0),移除Mesh collider组件
(3)将Assets/Materials目录下的fx_bolt_orange拖动到VFX上
(4)为Bolt添加一个Capsule Collider组件,勾选Is Trigger选项框,设置为一个触发器(注意这里的Capsule Collider组件只能放到Bolt上,不能放到子对象上,不然无法销毁Bolt对象,然后设置Capsule Collider的direction属性值为Y-Aixs,并设置radius为0.04,Height为0.65)
(5)新建一个Mover.cs绑定到Bolt上
public float speed=20.0f;
// Start is called before the first frame update
void Start()
{
GetComponent<Rigidbody>().velocity = Vector3.forward * speed;
}
(6)建立目录Perfabs,用来存储预制体,将Blot制作成一个预制体,建好之后,删除Hierarchy视图中的Bolt
(7)两个问题:不能通过键盘和鼠标发射,子弹不会自己消失或者销毁,数量巨大的子弹必定消耗非常多的系统资源,严重影响游戏的性能
2、用脚本控制发射子弹
(1)为player建立一个空的子对象shot spawn ,这是发射子弹的位置,position的值为(0,0,0.7),位置可以自己调整
(2)为了实现fire1触发后即刻实例化Bolt预制体,需要:
- 存储传入的Bolt游戏对象,作为Instantiate的第一个参数
- 存储发射器的位置,作为实例化Bolt的位置
- 设置一定的发射频率,只有间隔时间到了之后才能继续发射
(3)在PlayerController中书写代码
public float fireRate = 0.5f;//发射的间隔时间,默认是0.5秒
public GameObject shot; //shot表示的是Bolt预制体
public Transform shotSpawn;//子弹发射的位置
private float nextFire = 0.0f;//表示下次可以发射的最早时间(发射时间应该大于此值)从0开始 private void Update()
{
if(Input.GetButton("Fire1") && Time.time > nextFire){
nextFire = Time.time + fireRate;
Instantiate(shot, shotSpawn.position,Quaternion.identity);
}
}
3、管理子弹的声明周期
我们想要子弹飞出有效的游戏区域后自行销毁,因此可以为游戏区域增加触发器,当飞出的时候,在事件响应中调用Destroy方法
(1)创建一个Cube,重命名Boundary,重置Transform组件,设置数值,由于不用显示移除Mesh Renderer组件,
(2)创建脚本DestroyByBoundary.cs在其中添加响应的处理事件,OnTriggerExit,将其拖动到Boundary对象上。
private void OnTriggerExit(Collider other)
{
Destroy(other.gameObject);
}
四、添加小行星(Asteroid)
接下来可以在场景中添加小行星对象,实现的目标是:
- 小行星随机产生,且应该以随机的角度旋转
- 当飞船发射子弹击中小行星时,小行星会爆照并且销毁
- 若飞船碰撞到小行星,则飞船爆炸,游戏结束
1、创建小行星对象
(1)创建空对象,重命名为Asteroid,重置其Transform组件,设置position(0,0,10),添加Rigidbody组件,取消Use Gravity选项,将Angular Drag 设置为0;添加capsule collider组件,勾选Is Trigger选项。
(2)从Assets/Models拖动prop_asteroid_01到Asteroid对象上。成为Asteroid的子对象
(3)为了使碰撞体更接近模型的几何体形状,选中设置碰撞体的属性值Radius的值为0.5,Height的值为1.6,Direction为Z轴
2、添加控制小行星随机旋转的功能
(1)创建脚本RandomRotator.cs并且绑定到Asteroid对象上。
public float tumble = 10.0f;//小行星的旋转系数
// Start is called before the first frame update
void Start()
{
//设置刚体的角速度,角速度是描述做圆周运动的物体,单位时间旋转的角度
//Random.insideUnitSphere表示单位长度半径球体内的一个随机点(向量)
//记住将刚体的角阻力设置为0,不然会越转越慢(物体旋转是所受到的空气阻力)
GetComponent<Rigidbody>().angularVelocity = Random.insideUnitSphere * tumble;
}
3、添加控制射击小行星的功能
子弹射中小行星,二者会消失;飞船与小行星发生碰撞,二者会消失
(1)新建一个脚本DestroyByContact.cs,并且绑定的Asteroid对象上
(2)小行星在Boundary中,如果写直接写销毁代码,游戏一开始就会把小行星和Boundary销毁,所以要进行碰撞体检测,若是与Boundary碰撞不销毁,与其他的对象则执行销毁代码,方法之一是比较对象的Tag属性,设置Boundary的Tag为Boundary。
(3)添加代码
public class DestroyBy_Contact : MonoBehaviour
{
private void OnTriggerEnter(Collider other)
{
if(other.tag == "Boundary")
{
return;
}
Destroy(other.gameObject);
Destroy(gameObject);
}
}
4、添加小行星爆炸效果
(1)在脚本DestroyByContact中添加两个变量
public GameObject explosion;//小行星的爆炸粒子效果对象
public GameObject playerExplosion;//飞船爆炸的粒子效果对象
(2)在碰撞函数中添加实例化粒子效果的代码
//实例化爆炸效果
Instantiate(explosion, transform.position, transform.rotation);
if(other.tag == "Player")
{
Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
}
(3)在Assets/prefabs/VFX目录下拖动explosion_asteroid到变量explosion上,explosion_player到变量playerExplosion上
5、添加小行星移动的功能
(1)将Mover.cs脚本拖动到Asteroid上,设置Speed的值为-5,使小行星向与子弹运动方向相反的方向运行
6、添加小行星随机产生的逻辑功能
在添加随机产生小行星的逻辑功能之前,需要先制作Asteroid预制体
(1)将Asteroid拖动到Prefabs中,然后在hierarchy面板中删除
(2)创建一个空对象,重命名为GameController,重置其Transform组件,设置Tag为GameController
(3)创建GameController.cs脚本,并且拖动到GameController上
public GameObject hazard;//准备实例化的障碍物对象
public Vector3 spawnValues;//设置为(6,0,14.5)
private Vector3 spawnPosition = Vector3.zero;//实例化时的位置
private Quaternion spawnRotation;//实例化时的旋转 //用于在
void SpawnWaves()
{
//x在这个范围之间
spawnPosition.x = Random.Range(-spawnValues.x, spawnValues.x);
spawnPosition.z = spawnValues.z;
spawnRotation = Quaternion.identity;
Instantiate(hazard, spawnPosition, spawnRotation);
}
// Start is called before the first frame update
void Start()
{
SpawnWaves();
}
(4)将小行星预制体拖拽给hazard,spawnValues设置为(6,0,14.5)
(5)运行会发现随机位置生成
7、添加小行星批量产生的功能
(1)在GameController脚本中添加变量hazardCount,表示障碍物的数量
(2)修改SpawnWaves中的代码
public int spawnCount;//生成小行星的数量
//用于生成小行星
void SpawnWaves()
{
for (int i = 0; i < spawnCount; i++)
{
//x在这个范围之间
spawnPosition.x = Random.Range(-spawnValues.x, spawnValues.x);
spawnPosition.z = spawnValues.z;
spawnRotation = Quaternion.identity;
Instantiate(hazard, spawnPosition, spawnRotation);
} }
(3)设置数量为10,这样的话,,生成的小行星之间会互相碰撞销毁,为了解决这个问题,可以在每次生成一个小行星后等待一段时间,unity中提供协程类WaitForSeconds可以实现这样的功能
(4)再添加一个变量spawnWait,使用协程方法,修改函数。并且修改调用方法,设置变量的是为0.5
(5)由于不想一开始就生成小行星,可以在设置一个变量startWait,在for循环的上面添加一段代码,保存,设置startwait为1
(6)如果想不断的产生多波小行星,可以添加一个变量waveWait,表示两波之间的时间间隔,写个无限循环,将for包进去,并且加上延迟waveWait
public GameObject hazard;//准备实例化的障碍物对象
public Vector3 spawnValues;//
private Vector3 spawnPosition = Vector3.zero;//实例化时的位置
private Quaternion spawnRotation;//实例化时的旋转 public int spawnCount;//生成小行星的数量
public float spawnWait;//设置产生小行星的时间间隔 public float startWait;//设置等待时间,之后产生小行星
public float waveWait;//两波小行星之间的时间间隔
//用于生成小行星
IEnumerator SpawnWaves()
{
//等待startWait秒之后生成行星
yield return new WaitForSeconds(startWait);
//不断产生行星
while (true)
{
for (int i = 0; i < spawnCount; i++)
{
//x在这个范围之间
spawnPosition.x = Random.Range(-spawnValues.x, spawnValues.x);
spawnPosition.z = spawnValues.z;
spawnRotation = Quaternion.identity;
Instantiate(hazard, spawnPosition, spawnRotation);
//生成每个行星的时间间隔
yield return new WaitForSeconds(spawnWait);
}
//两波波行星生成的时间间隔
yield return new WaitForSeconds(waveWait);
} }
// Start is called before the first frame update
void Start()
{
StartCoroutine(SpawnWaves()); }
(7)设置waveWait的值为2,运行游戏,发现可以不断的生成小行星,但是发现击中小行星几次后,爆炸粒子效果explosion_asteroid没有自动销毁,随着游戏的进行,严重的影响了游戏的美观和效率。
(8)新建一个脚本DestroyByTime.cs并且绑定到粒子效果上面。
public class DestrtroyByTime : MonoBehaviour
{
//表示的是粒子的声明周期默认2秒
public float lifeTime = 2.0f; // Start is called before the first frame update
void Start()
{
//在lifeTime秒之后销毁物体
Destroy(gameObject, lifeTime);
}
}
(9)运行游戏,已经ok了
五、添加游戏音频
1、添加碰撞爆炸音频
(1)将project视图变成单列布局,两列的不好弄
(2)将Assets/Audio中将对应的音频文件拖动到Assets/VFX/Explosions中预制体对象上。确保Play On Awake选项勾选
2、添加飞船射击音效
(1)将音频文件拖动到player上,取消勾选Play On Awake选项,不然一开始就会响
(2)在PlayerController脚本中添加以下代码,运行发射子弹就可以听到声音
if(Input.GetButton("Fire1") && Time.time > nextFire){
...............//调用audiosource类中成员函数Play来播放声音
GetComponent<AudioSource>().Play();
}
3、添加背景音效
理论上,背景音乐可以放到场景中任意一个处于活动状态的游戏对象上,这里选择的是在GameController上
上面讲直接拖动音频文件到目标对象的方法添加音频,简介高效。但不利于读者理解unity管理音频的过程,下面采用另外一种方法来添加音频。
(1)在GameController上添加一个AudioSource组件,此时Audio Clip属性为空。
(2)讲背景音乐拖动到Audio Clip中,这样就可以绑定到GameController上了
(3)由于背景音乐从游戏开始连续不断的播放,所以Play On Awake和Loop都要勾选上
六、添加计分文本
(1)创建Text,会自动添加一个 Canvas父对象和EventSystem对象,重命名Text为Score Text,Text组件中的Text属性输入:得分
(2)将其放到场景的左上角:
(3)添加计分功能;在GameController中添加两个变量:之后再创建函数并进行初始化
public Text scoreText;//Text组件
private int score;//分数
void Start()
{
//初始化分数和Text组件
score = 0;
updateScore();
StartCoroutine(SpawnWaves());
}
//创建一个增加和更新分数的组件
public void AddScore(int newScoreValue)
{
score += newScoreValue;
updateScore();
}
private void updateScore()
{
scoreText.text = "得分:" + score;
}
}
(4)在DestroyByContact脚本中加入变量
public int scoreValue;//设置小行星的分数
private GameController gameController;//创建一个GameController类的变量
(5)在小行星碰撞事件函数中OnTriggerEnter中添加分值更新语句
//增加分数
gameController.AddScore(scoreValue);
(6)在函数start中初始化变gameController,我们不能直接得到GameController脚本,需要找到GameController对象,在得到绑定在上面的GameController脚本
private void Start()
{
GameObject go = GameObject.FindWithTag("GameController");
if(go != null)
{
gameController = go.GetComponent<GameController>();
}
else
{
Debug.Log("找不到tag为GameController的对象");
}
if(gameController == null)
{
Debug.Log("找不到为GameController脚本");
}
}
(7)在GameController对象中将Score Text拖进去,在Asteroid预制体中设置分数为10
七、游戏结束与重新开始
当飞船销毁后,游戏应该结束,并且用户能够选择重新开始游戏
1、设置游戏结束的文本,创建Text 设置游戏结束的字体,居中显示
2、添加游戏结束的功能
(1)打开脚本GameController脚本,添加变量
public Text gameOverText;//游戏结束显示的文本
public bool gameOver;//游戏是否结束的标志
(2)在Start中赋值,游戏开始时应该清除文本
//游戏刚开始,文本清除,同时设置gameOver为false
gameOverText.text = "";
gameOver = false;
(3)在脚本中添加一个GameOver函数,用来表示游戏的结束
public void GameOver()
{
gameOver = true;
gameOverText.text = "游戏结束";
}
(4)在SpawnWaves中,当gameOver为true时,应该跳出while 循环
//不断产生行星
while (true)
{
//如果游戏结束,跳出循环
if (gameOver)
{
break;
}
(5)将场景中的游戏结束的文本,拖拽给gameOverText变量,unity会自动的赋值
(6)打开脚本DestroyByContact,当小行星碰撞的是player对象的时候,游戏结束(注意检查player的Tag是不是设置成了Player)
if (other.tag == "Player")
{
.............
//调用游戏结束的函数
gameController.GameOver();
}
(7)运行游戏,当飞船与小行星碰撞后,游戏结束
3、重新开始游戏
1、创建一个Text,重命名restartText,拖动选择好合适的位置,Text属性写: 按下【R】键重新开始,调整好大小
2、添加重新开始的代码
(1)打开脚本GameController脚本,添加变量
public Text restartText;//重新开始的文本
private bool restart;//游戏是否从新开始的标志
(2)在Start中赋值,游戏开始时应该清除文本
//游戏开始,文本清除,同时设置restart为false
restartText.text = "";
restart = false;
(3)在SpawnWaves函数中,当游戏结束时,添加代码
//如果游戏结束,跳出循环
if (gameOver)
{
restartText.text = "按下【R】键重新开始";
restart = true;
break;
(4)在Update函数中,添加代码
private void Update()
{
if (restart)
{
if (Input.GetKeyDown(KeyCode.R))
{
//Application.LoadLevel(Application.loadedLevel);已经弃用
SceneManager.LoadScene("Space_Shooter");//小括号里可以填写场景的名字
}
}
}
新手上路可以一起交流哦!
unity官方案例精讲(第三章)--星际航行游戏Space Shooter的更多相关文章
- Unity官方案例精讲_2015_优化
1.将公共变量从Inspector视图中隐藏: [HideInInspector] [HideInInspector] public GameObject player; 2.限定Inspect ...
- 微软BI SSIS 2012 ETL 控件与案例精讲面试 200 问(SSIS 面试题,ETL 面试题)
开篇介绍 本自测与面试题出自 微软BI SSIS 2012 ETL 控件与案例精讲 (http://www.hellobi.com/course/21) 课程,对于学完本课程的每一课时和阅读完相关辅助 ...
- 微软BI SSIS 2012 ETL 控件与案例精讲课程学习方式与面试准备详解
开篇介绍 微软BI SSIS 2012 ETL 控件与案例精讲 (http://www.hellobi.com/course/21) 课程从2014年9月开始准备,到2014年12月在 天善BI学院 ...
- (转)linux route命令深入浅出与实战案例精讲
linux route命令深入浅出与实战案例精讲 http://blog.51cto.com/oldboy/1119453 深入浅出之-route命令实战使用指南 http://blog.51cto. ...
- javascript面向对象精要第三章对象整理精要
什么是对象的数据属性?什么是对象的访问器属性?[put]方法是默认创建数据属性的,访 问器属性不包含值而是定义了一个单属性被读取时调用的函数(getter)和当一个属性被写入时 调用的函数(sette ...
- Linux高频命令精讲(三)
[教程主题]:2.Linux高频命令精讲 [2.1]Linux的运行方式 图形运行方式 - 本地使用KDE/Gnome集成环境 - 运行X Server远程使用图形环境 命令行(字符运行)方式 - 本 ...
- (转)不看绝对后悔的Linux三剑客之awk实战精讲
原文:http://blog.51cto.com/hujiangtao/1923930 一.Linux三剑客之awk命令精讲 第1章 awk基础入门 1.1 awk简介 awk不仅仅时linux系统中 ...
- Unity Shader入门精要学习笔记 - 第10章 高级纹理
转载自 冯乐乐的 <Unity Shader入门精要> 立方体纹理 在图形学中,立方体纹理是环境映射的一种实现方法.环境映射可以模拟物体周围的环境,而使用了环境映射的物体可以看起来像镀了层 ...
- Unity Shader入门精要学习笔记 - 第6章 开始 Unity 中的基础光照
转自冯乐乐的<Unity Shader入门精要> 通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑3种物理现象. 首先,光线从光源中被发射出来. 然后,光线和场景中的一些物体相交 ...
随机推荐
- 常用注解@Intdef与@Stringdef
1.优点 可以代替枚举,静态常量,可以让注解只在代码中存在,编译后就删除,可以省内存. 2.@IntDef 2.1 官网 https://developer.android.com/reference ...
- unity3d屏幕截图功能
function OnGUI(){ if(GUI.Button(Rect(Screen.width*0.5-50,Screen.height*0.5-50,100,100),"screen& ...
- IMGUI
https://github.com/zwcloud/ImGui https://github.com/ocornut/imgui https://usingcpp.wordpress.com/201 ...
- 写shader小细节——这个会不断更新
这个是因为自己被自己蠢哭了动笔的,里面大概记录自己所犯的错,和一些小知识. 1.有一个错误我经常犯:内部定义的字段没对应开放到编辑器的字段.这个是由于我有点依赖ide写代码的习惯导致,而shader的 ...
- P1090 合并果子(哈弗曼树)
题目描述 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和.可 ...
- 使用IDEA写Python之pytest环境搭建及第一个程序编写
一.准备篇 Python环境:3.8.3 开发工具:IDEA,对你没有看错 二.IDEA下安装开发环境 1. python的下载 https://www.python.org/downloads/ P ...
- 线上环境去除console
npm i -D babel-plugin-transform-remove-console babel.config.js // 获取 VUE_APP_ENV 非 NODE_ENV,测试环境依然 c ...
- 知识点干货——CSS动画
CSS动画 (transition.animation) //2D动画 transform:translate(); /*偏移*/ transform:rotate(); /*旋转角度*/ trans ...
- SpringBoot—整合log4j2入门和log4j2.xml配置详解
关注微信公众号:CodingTechWork,一起学习进步. 引言 对于一个线上程序或者服务而言,重要的是要有日志输出,这样才能方便运维.而日志的输出需要有一定的规划,如日志命名.日志大小,日志分 ...
- Oracle中select子句取值先于order by子句执行而导致rownum伪列未按预期取值导致的问题
有这么一张表: create table hytb( id number(4,0) not null primary key, padid nvarchar2(20) not null, inputd ...