游戏开发的要素
一帧一帧的写,然后循环执行
Unity的工作的是就是重复性的工作,降低开发门槛
Uinty3D工程
视图
- scene
简单逻辑:创建一个GameObject对象,运动,然后用Main Camera拍摄下来
Gameobject
GameObject被【Inspector窗口下】若干个Component所控制,其中默认的是transform属性【位置、旋转方向、比例】
创建方向光->点选main camrea,改变参数postion,形成了物体的【运动】
【停止运行】后scene 回到了初始静止的状态
- game
- hierarchy(分层视图)
- project
assets文件夹中包含你需要用到的资源
【windows】-layouts ,tall布局选择你想要的布局类型
scene
x,y,z三个方向,一些缩放,移动小tools-button,对象【Gizmos】中的box-collider是碰撞框,检测是否发生碰撞
gameobject
- 系统自带的一些地形,树木等;他们会内置一些compoment;
- 定义对象的父子关系,会一起响应【一些参数的改变】
- prefab[预制件],从hierarchy中拖动到Project中会变成prefab[蓝色]
【游戏发布】,[buildsettings]-[platfrom]
Uinty3d资源管理
美术资源管理
比如Textures【纹理贴图】,导入图片后自己会变成相关的格式
U3d角色控制
素材的常见属性,mesh的属性texture和shalder
collider:
box collider碰撞再一起,会产生一个事件,由你区处理
配置好环境素材的属性
添加一个player,摄像机对准,静态场景搭建完成。
游戏动起来,c# & UnityScript
凡是能够挂在Gameobject上的都是Component,Script是一种特殊的脚本若想要挂在gameobject,都是继承了MonoBehaviour类
Unity如何驱动游戏
对准摄像机
在Update()中加入实现移动
Update()
{
WalkForward();
}
void WalkForward()
{
transform.position = transform.position + walkSpeed * transform.forward * Time.deltaTime ;
}
摄像头跟随Player
void Start ()
{
GameObject.Find ("Main Camera").GetComponent<SceneCamera> ().player = this.gameObject;
}
void LateUpdate()
{
if(player != null)
camera.transform.LookAt(player.transform.position);//相机盯住player的位置信息,一帧更新一次
}
响应用户输入,操作物体
用键盘和鼠标控制角色移动
1.设置用户输入
2.检测是否有相关的外部输入
edit - project settings - inputManager
1.用键盘控制用户输入
void Update ()
{
Debug.Log ("Horizontal value: " + Input.GetAxis ("Horizontal"));//检测有无输入(在-1到1之间)
Vector3 direction = Input.GetAxis ("Horizontal") * transform.right +
Input.GetAxis ("Vertical") * transform.forward; //按键*方向向量
movement.movementDirection = direction.normalized; //direction根据输入计算出来
if (bWalking) {
bWalking = Walking ();
} else {
}
}
2.鼠标控制移动,检测是否有click事件,然后执行clickon(目标位置);
void Update () {
// _clickListener.Update();
if (Input.GetMouseButtonUp (0)) {
ClickOn( Input.mousePosition );
}
}
void ClickOn(Vector2 pos)//从摄像机摄出一段射线,看看击中哪个点【与collider相碰】,然后计算出该点的位置,移动。
{
if (player == null)
return;
Ray ray = this.GetComponent<Camera>().ScreenPointToRay(pos);
RaycastHit[] hits = Physics.RaycastAll(ray);
foreach (RaycastHit hit in hits){
BoxCollider bc = hit.collider as BoxCollider;
if (bc != null && bc.name.Contains("floor") && player != null){
player.GetComponent<Player>().WalkTo(hit.point);
break;
}
}
}
动画导入(移动时身体动画)
添加Animator componment组件
选择状态机,然后用脚本控制状态机
跳转条件,播放多长时间,退出当前状态,跳转到相应状态
只能从一个确定的状态发起到一个不确定的状态
// player Animaiton
void Update () {
Vector3 velocity = GetComponent<Rigidbody> ().velocity;//(tr.position - lastPosition) / Time.deltaTime;
localVelocity = tr.InverseTransformDirection (velocity);
localVelocity.y = 0;
speed = localVelocity.magnitude;
angle = ( HorizontalAngle (localVelocity) + 360f )%360f;
lastPosition = tr.position;
animator.SetFloat ("Speed", speed);
animator.SetFloat ("Angle", angle);
// Debug.Log ("Speed: " + speed + " Angle: " + angle);
}
void FixedUpdate () {
}
static float HorizontalAngle (Vector3 direction) {
return Mathf.Atan2 (direction.z, direction.x) * Mathf.Rad2Deg;
}
动态生成物品和销毁(发射子弹/销毁子弹)
void Update ()
{
if (firing) {
if (Time.time > lastFireTime + 1 / frequency) {
//枪口抖动
var coneRandomRotation = Quaternion.Euler (Random.Range (-coneAngle, coneAngle), Random.Range (-coneAngle, coneAngle), 0);
GameObject go = Instantiate(bulletPrefab, spawnPoint.position, spawnPoint.rotation * coneRandomRotation) as GameObject;//使用instantiate动态生成bullet的预制件
//Spawner.Spawn (bulletPrefab, spawnPoint.position, spawnPoint.rotation * coneRandomRotation) as GameObject;
Bullet bullet = go.GetComponent<Bullet> ();
lastFireTime = Time.time;
bullet.dist = 1000;
}
}
}
void OnStartFire () { //检测是否收到开火信号
if (Time.timeScale == 0)
return;
firing = true;
// if (GetComponent<AudioSource>())
// GetComponent<AudioSource>().Play ();
}
void OnStopFire () {
firing = false;
// if (GetComponent<AudioSource>())
// GetComponent<AudioSource>().Stop ();
}
销毁子弹
Bullet.cs
public float speed = 10f;
public float lifeTime = 0.5f;
public float dist = 10000;
private float spawnTime = 0.0f;
private Transform tr ;
// private Health _health;
void OnEnable () { //子弹出生时间为当前时间
tr = transform;
spawnTime = Time.time;
}
void Update () {
tr.position += tr.forward * speed * Time.deltaTime;
dist -= speed * Time.deltaTime;
if (Time.time > spawnTime + lifeTime || dist < 0) { //满足指定条件后会被销毁
// Destroy (gameObject);
Spawner.Destroy (gameObject);
}
}
//鼠标发射
public class TriggerOnMouse : MonoBehaviour {
public SignalSender mouseDownSignals ;
public SignalSender mouseUpSignals ;
public GameObject target;
void Update () {
if (Input.GetMouseButtonDown (0))
target.SendMessage ("OnStartFire");
if (Input.GetMouseButtonUp(0))
target.SendMessage ("OnStopFire");
}
}
一些问题
使用cache优化
新建spanwer gameobject,添加对bullet prefab的引用,添加spanwer scripts设置size为20,修改bullet.cs的析构,和Weapon.cs中的Instantiate
Spawner.Spawn (bulletPrefab, spawnPoint.position, spawnPoint.rotation * coneRandomRotation) as GameObject;//替换Instantiate(bulletPrefab, spawnPoint.position, spawnPoint.rotation * coneRandomRotation) as GameObject;
开机存在20个非活跃的bullet子弹缓存空间,然后重复挨个激活到去活跃的过程。
U3d角色交互
子弹碰到物体后
在墙mesh,中添加box collider各种类型的collider,mesh collider检测最精确但性能最差
void OnTriggerEnter(Collider other) //碰到物体瞬间
{
Debug.Log ("collision with: " + other.gameObject.name);
// if (other.tag != "AI_Trigger" && other.tag != "Damage_Trigger")
{
Spawner.Destroy (gameObject);
// _health = other.GetComponent<Health>();
// if( _health != null )
// _health.OnDamage();
}
}
void OnTriggerStay(Collider other) //碰到持续
{
Debug.Log ( "collider stay" );
}
void OnTriggerExit(Collider other) //碰到后
{
Debug.Log ( "collider exit" );
}
//加入rigidbody,不会触发上述情况,但会形成一些(刚体)物理的效应
void OnCollisionEnter(Collision collision)
{
Debug.Log ("collision with: " + collision.gameObject.name);
Spawner.Destroy (gameObject);
}
void OnCollisionStay(Collision other)
{
Debug.Log ( "collision stay" );
}
void OnCollisionExit(Collision other)
{
Debug.Log ( "collision exit" );
}
Rigidbody
给人物添加Rigidbody componment,避免穿墙
drug 阻力
前两个是持续施加的速度和力,后两个是瞬时的
鼠标拖动控制枪口方向
facingDirection是当前面对方向
AngleAroundAxis是绕指定轴旋转的角速度,
GetComponent<>为转动函数
加入敌人
代码逻辑
AI
使用stateMachine控制敌人
下属多个scrips
scanner,shooting,waiting(default);
设置多个球形collider,检测触发事件
unity内置的NavMeshAgent来控制Npc绕过障碍物,行进等。
生成Navmesh导航网格
UI系统
Gameobject -> UI ->Cavas(画布)
然后在建立button作为Cavas的子结点
通过锚点,定位Button。
设置每个button的gameconsler属性
###################################################
项目来源:慕课网-Unity3D快速来源
#################################################