unity3d使用说明
第一篇:unity3d使用说明
Unity3D中的预制件(Prefab)的创建和使用说明!!!
首先我说明一下什么预制件?
在U3D里面我们叫它Prefab;我们可以这样理解:当制作好了游戏组件(场景中的任意一个gameobject),我们希望将它制作成一个组件模版,用于批量的套用工作,例如说场景中本质上“重复”的东西,“敌人”,“士兵”,“子弹”。。。。。。这里说本质是因为默认生成的prefab其实和模版是一模一样的,就像是克隆体,但生成的位置和角度以及生成后的一些属性是允许发生变化的。
如何制作Prefab?
首先创建一个prefab的文件夹吧~
接着我在场景中创建一个备选预制件组件,这里就直接创建一个cube好了
这里有两种方法将这个cube变更为预制件
1.直接将cube拖拽到_Prefabs的文件夹里。(真的超简单)
2.先在_Prefabs的文件夹里创建一个预制件
接着将cube拓展到这个预制件上面。
现在看看场景中的cube可以在inspector面板中看到多了这样一栏,点击select可以定位到project中的预制件模版“母体”,revert就是还原当前预制件,apply就是确定当前预制件罗~好吧,我不想把各位当成傻瓜,有兴趣可以自己动手试试他们的作用。
如何在场景中创建预制件?
创建一个脚本,好吧~
写一个暴露变量用于记录预制件的“母体”
接着在鼠标点击时创建,我这里创建的位置和旋转都为0。
现在布置一下脚本和变量:
运行点击屏幕:
可以注意到场景的面板中创建了很多的“克隆体”。
第二篇:总结使用Unity3D优化游戏运行性能的经验
流畅的游戏玩法来自流畅的帧率,而我们即将推出的动作平台游戏《Shadow Blade》已经将在标准iPhone和iPad设备上实现每秒60帧视为一个重要目标。
以下是我们在紧凑的优化过程中提升游戏运行性能,并实现目标帧率时需要考虑的事项。--来自狗刨学习网
当基本游戏功能到位时,就要确保游戏运行表现能够达标。我们衡量游戏运行表现的一个基本工具是Unity内置分析器以及Xcode分析工具。使用Unity分析器来分析设备上的运行代码真是一项宝贵的功能。
我们总结了这种为将目标设备的帧率控制在60fps而进行衡量、调整、再衡量过程的中相关经
一、遇到麻烦时要调用“垃圾回收器”(Garbage Collector,无用单元收集程序,以下简称GC)
由于具有C/C++游戏编程背景,我们并不习惯无用单元收集程序的特定行为。确保自动清理你不用的内存,这种做法在刚开始时很好,但很快你就公发现自己的分析器经常显示CPU负荷过大,原因是垃圾回收器正在收集垃圾内存。这对移动设备来说尤其是个大问题。要跟进内存分配,并尽量避免它们成为优先数,以下是我们应该采取的主要操作:
1.移除代码中的任何字符串连接,因为这会给GC留下大量垃圾。
2.用简单的“for”循环代替“foreach”循环。由于某些原因,每个“foreach”循环的每次迭代会生成24字节的垃圾内存。一个简单的循环迭代10次就可以留下240字节的垃圾内存。
3.更改我们检查游戏对象标签的方法。用“if (go.CompareTag (“Enemy”)”来代替“if (go.tag == “Enemy”)” 。在一个内部循环调用对象分配的标签属性以及拷贝额外内存,这是一个非常糟糕的做法。
4.对象库很棒,我们为所有动态游戏对象制作和使用库,这样在游戏运行时间内不会动态分配任何东西,不需要的时候所有东西反向循环到库中。
5.不使用LINQ命令,因为它们一般会分配中间缓器,而这很容易生成垃圾内存。
二、谨慎处理高级脚本和本地引擎C++代码之间的通信开销。
所有使用Unity3D编写的游戏玩法代码都是脚本代码,在我们的项目中是使用Mono执行时间处理的C#代码。任何与引擎数据的通信需求都要有一个进入高级脚本语言的本地引擎代码的调用。这当然会产生它自己的开销,而尽量减少游戏代码中的这些调用则要排在第二位。
1.在这一情景中四处移动对象要求来自脚本代码的调用进入引擎代码,这样我们就会在游戏玩法代码的一个帧中缓存某一对象的转换需求,并一次仅向引擎发送一个请求,以便减少调用开销。这种模式也适用于其他相似的地方,而不仅局限于移动和旋转对象。
2.将引用本地缓存到元件中会减少每次在一个游戏对象中使用 “GetComponent” 获取一个元件引用的需求,这是调用本地引擎代码的另一个例子。
三、物理效果
1.将物理模拟时间步设置到最小化状态。在我们的项目中就不可以将让它低于16毫秒。
2.减少角色控制器移动命令的调用。移动角色控制器会同步发生,每次调用都会耗损极大的性能。我们的做法是缓存每帧的移动请求,并且仅运用一次。
3.修改代码以免依赖“ControllerColliderHit” 回调函数。这证明这些回调函数处理得并不十分迅速。
4.面对性能更弱的设备,要用skinned mesh代替physics cloth。cloth参数在运行表现中发挥重要作用,如果你肯花些时间找到美学与运行表现之间的平衡点,就可以获得理想的结果。
5.在物理模拟过程中不要使用ragdolls,只有在必要时才让它生效。
6.要谨慎评估触发器的“onInside”回调函数,在我们的项目中,我们尽量在不依赖它们的情况下模拟逻辑。
7.使用层次而不是标签。我们可以轻松为对象分配层次和标签,并查询特定对象,但是涉及碰撞逻辑时,层次至少在运行表现上会更有明显优势。更快的物理计算和更少的无用分配内存是使用层次的基本原因。
8.千万不要使用Mesh对撞机。
9.最小化碰撞检测请求(例如ray casts和sphere checks),尽量从每次检查中获得更多信息。
四、让AI代码更迅速
我们使用AI敌人来阻拦忍者英雄,并同其过招。以下是与AI性能问题有关的一些建议:
1.AI逻辑(例如能见度检查等)会生成大量物理查询。可以让AI更新循环设置低于图像更新循环,以减少CPU负荷。
五、最佳性能表现根本就不是来自代码!
没有发生什么情况的时候,就说明性能良好。这是我们关闭一切不必要之物的基本原则。我们的项目是一个侧边横向卷轴动作游戏,所以如果不具有可视性时,就可以关闭许多动态关卡物体。
1.使用细节层次的定制关卡将远处的敌人AI关闭。
2.移动平台和障碍,当它们远去时其物理碰撞机也会关闭。
3.Unity内置的“动画挑选”系统可以用来关闭未被渲染对象的动画。
4.所有关卡内的粒子系统也可以使用同样的禁用机制。
六、回调函数!那么空白的回调函数呢?
要尽量减少Unity回调函数。即使敌人回调函数存在性能损失。没有必要将空白的回调函数留在代码库中(有时候介于大量代码重写和重构之间)。
七、让美术人员来救场
在程序员抓耳挠腮,绞尽脑汁去想该如何让每秒运行更多帧时,美术人员总能神奇地派上大用场。
1.共享游戏对象材料,令其在Unity中处于静止状态,可以让它们绑定在一起,由此产生的简化绘图调用是呈现良好移动运行性能的重要元素。
2.纹理地图集对UI元素来说尤其有用。
3.方形纹理以及两者功率的合理压缩是必不可少的步骤。
4.我们的美术人员移除了所有远处背景的网格,并将其转化为简单的2D位面。
5.光照图非常有价值。
6.我们的美术人员在一些关口移除了额外顶点。
7.使用合理的纹理mip标准是一个好主意(注:要让不同分辨率的设备呈现良好的帧率时尤其如此)。
8.结合网格是美术人员可以发挥作用的另一个操作。
9.我们的动画师尽力让不同角色共享动画。
10.要找到美学/性能之间的平衡,就免不了许多粒子效果的迭代。减少发射器数量并尽量减少透明度需求也是一大挑战。
八、要减少内存使用
使用大内存当然会对性能产生负面影响,但在我们的项目中,我们的iPod由于超过内存上限而遭遇了多次崩溃事件。我们的游戏中最耗内存的是纹理。
1.不同设备要使用不同的纹理大小,尤其是UI和大型背景中的纹理。《Shadow Blade》使用的是通用型模板,但如果在启动时检测到设备大小和分辨率,就会载入不同资产。
2.我们要确保未使用的资产不会载入内存。我们必须迟一点在项目中找到仅被一个预制件实例引用,并且从未完全载入内存中实例化的资产。
3.去除网格中的额外多边形也能实现这一点。
4.我们应该重建一些资产的生周期管理。例如,调整主菜单资产的加载/卸载时间,或者关卡资产、游戏音乐的有效期限。
5.每个关卡都要有根据其动态对象需求而量身定制的特定对象库,并根据最小内存需求来优化。对象库可以灵活一点,在开发过程中包含大量对象,但知道游戏对象需求后就要具体一点。
6.保持声音文件在内存的压缩状态也是必要之举。
加强游戏运行性能是一个漫长而具有挑战性的过程,游戏开发社区所分享的大量知识,以及Unity提供的出色分析工具为《Shadow Blade》实现目标运行性能提供了极大帮助。
第三篇:Unity3D编写雷电游戏
基础实用的一篇经验教程!
一、搭建游戏的框架。
一般的游戏都可以分为四个场景:
1.开始界面
2.游戏场景
3.暂停界面
4.结束界面
开始界面,就是存放开始菜单的地方了,游戏场景就是游戏的主场景,游戏的主要元素都在这边体现,暂停和结束画面我就不多说了。更多的还有在开始和主游戏场景之间加入过场动画等等。当然你也可以在暂停界面中插入广告
我们会发现这几个场景之间其实就是切换来切换去的关系。如果知道设计模式中的State模式,就会发现跟这个很象。可以通过State模式来实现这几个场景的分离,然后分边为他们添加不同的元素。
想要挂接在Unity3D中的结点的脚本都得继承MonoBehaviour,State就是所有的状态的父类了,主要是三个函数,Init()用于这个状态的初始化,Update用于场景的更新,Exit()用于当离开当前状态时所进行的一些操作,比如隐藏当前界面等。
创建一个空的Object用来挂接我们游戏的主脚本,代码如下:
using UnityEngine; using System.Collections; public class Main_Script : MonoBehaviour { public State m_CurState; public void ChangeState(State newState) { m_CurState.Exit(); m_CurState = newState; m_CurState.Init(); } // Use this for initialization void Start () { m_CurState.Init(); } // Update is called once per frame void Update ()
{ m_CurState.Update(); } } 这样我们就可以轻松的在不同的状态中切换了。想要增加一个新的状态,就只需继承State类,然后在其中写这个状态所要的元素,在适当的地方ChangeState一下就好了。
脚本的层次结构如下: 例如我在按钮按下时切换到开始场景:
using System.Collections; public class BeginGame : MonoBehaviour { public StateRun m_RunState; public Main_Script m_MainScript; // Use this for initialization void Start () { } // Update is called once per frame void Update () { } void OnMouseEnter() { print("enter"); } void OnMouseUp() { m_MainScript.ChangeState(m_RunState); } void OnMouseExit() { print("exit"); } } 这个脚本是挂在一个板上面的,点击它时就进入游戏的主场景了。下回说一下飞机的移动。
现在开始真正的游戏元素的编写了。
第一步,让飞机动起来。
首先是飞机的前进,通常2D中的做就是背景的循环滚动。
在3D中我们可以让摄像机移动,背景我们可以做超一个大地形。。在地形上摆一些固定的东西。
// Update is called once per frame void Update () { TurnLeft = false; TurnRight = false; if (Input.GetKey(KeyCode.W)) {
Vector3 screenPos = Camera.mainCamera.WorldToScreenPoint(this.transform.position); //print(screenPos.y); if (Screen.height > screenPos.y) this.transform.Translate(Vector3.forward * Time.deltaTime * m_nMoveSpeed); } if (Input.GetKey(KeyCode.S)) { Vector3 screenPos = Camera.mainCamera.WorldToScreenPoint(this.transform.position); if (0 < screenPos.y) this.transform.Translate(Vector3.forward * Time.deltaTime * -m_nMoveSpeed); } if (Input.GetKey(KeyCode.A)) { Vector3 screenPos = Camera.mainCamera.WorldToScreenPoint(this.transform.position); if (0 < screenPos.x) this.transform.Translate(Vector3.left * Time.deltaTime * m_nMoveSpeed); //向左转
if (CurRotation < RotateLimit) { print(CurRotation); CurRotation += RotateSpeed; } TurnLeft = true; } if (Input.GetKey(KeyCode.D)) { Vector3 screenPos = Camera.mainCamera.WorldToScreenPoint(this.transform.position); if (Screen.width > screenPos.x) this.transform.Translate(Vector3.left * Time.deltaTime * -m_nMoveSpeed); //向右转
if (CurRotation > -RotateLimit) CurRotation -= RotateSpeed; TurnRight = true; } //回归
if (!TurnLeft && !TurnRight) { if (CurRotation > 0.0) CurRotation -=RotateSpeed; else if (CurRotation < 0) CurRotation +=RotateSpeed; } Quaternion rot = Quaternion.AngleAxis(CurRotation, new Vector3(0, 0, 1)); m_Plane.rotation = rot;
//让相机和飞机一起以一定的速度前移
this.transform.Translate(Vector3.forward * Time.deltaTime * m_nMoveSpeed); Camera.mainCamera.transform.Translate(Vector3.up * Time.deltaTime * m_nMoveSpeed); } 飞机的主要控制代码。。不知为什么,我的两个角度限制没有效果。。郁闷。。有空还看一下。。
这次先加入子弹的发射吧,没用模型,先用的一个capsule的prefab代替吧。
一想到各种武器之间的随意切换,就不由的想到了设计模式中的Strategy模式。
有关策略模式的详细介绍可以通过百度和维基来学习。
这个模式其实和State模式差不多。
Weapon类是所有武器的基类,新的武器继承于它,设置发射点,子弹模型,然后实现Fire函数就可以了。
WeaponManager用于管理所有武器,切换武器。
using UnityEngine; using System.Collections; public class WeaponManager : MonoBehaviour { public Weapon m_CurWeapon; private float m_FireElapseTime = 0;
// Use this for initialization void Start () { } // Update is called once per frame void Update () { m_FireElapseTime += Time.deltaTime; if (Input.GetKey(KeyCode.Space)) { if ( m_FireElapseTime > m_CurWeapon.GetBulletInterval()) { m_CurWeapon.Fire(); m_FireElapseTime = 0; } else { } } } } 记录子弹发射后的时间,然后在大于时间间隔后才能发射下一个子弹。
武器父类:
using UnityEngine; using System.Collections; using System; public class Weapon : MonoBehaviour { //子弹时间间隔
protected float m_fBulletInterval = 0; //子弹类型
public String m_typeName =""; public float GetBulletInterval() { return m_fBulletInterval; } // Use this for initialization void Start () { } // Update is called once per frame void Update () { } public virtual void Fire() { } } 最基本的一种子弹:
using UnityEngine; using System.Collections; public class WeaponNormal : Weapon { private const int MAX_FP = 2; public Transform[] m_FirePoint = new Transform[MAX_FP]; public Rigidbody m_BulletPre; WeaponNormal() { m_fBulletInterval = 2; m_typeName = "Normal"; } // Use this for initialization void Start () { } // Update is called once per frame void Update () { } public override void Fire() { for(int i = 0; i < MAX_FP; i++) { Rigidbody clone = (Rigidbody)Instantiate(m_BulletPre, m_FirePoint[i].position, m_FirePoint[i].rotation); clone.velocity = transform.TransformDirection(Vector3.forward * 20); } } } m_FirePoint是一个数组,存储了发射子弹的位置。在编辑器中,可以在飞机周围用空的GameObject放置一系列炮口的位置,然后拖入这个数组中。MAX_FP定义了炮口的数量。这里边用到了速度属性,这个是rigidbody才有的,所以在设置子弹的prefab时一定要为它加上rigidbody才行。 结构如下图所示:
最后的效果图:
现在子弹出来了,但是我们没有加上子弹的消亡,这样子弹被创建出来后就一直存在于场景中不会消失,会越积越多,所以我们让子弹在移出屏幕时就把他销毁掉。
using UnityEngine; using System.Collections; public class BulletControl : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () {
Vector3 screenPos = Camera.mainCamera.WorldToScreenPoint(this.transform.position); //print(screenPos.y); if (Screen.height < screenPos.y) Destroy(transform.gameObject); } } 将这个脚本挂接在子弹的prefab上就可以实现效果了。
己方的飞机控制已经初步完成了,现在要加入敌机了。
理论上应该有两种方式:
1.预先设定,就是在编辑器里在你想要的位置上加上敌方的攻击单位
2.动态生成,根据游戏进行的时间来控制敌方攻击单位的产生。
这边采用第2个方式来产生,有一些地面单位倒是可以用第一种方式来产生。
我们首先要设置一个敌机的产生位置,用空的object可以随意的定一个坐标。
using UnityEngine; using System.Collections; public class EnemyManager : MonoBehaviour { public GameObject m_EnemyPre; public Transform m_CreatePoint; //一波飞机的数量
public const int MAX_GROUP_ENEMYS = 4; //两波飞机之间的时间间隔
public float GROUP_INTERVAL = 2.0f; //同一波中两架飞机之间产生的间隔
public float CREATE_INTERVAL = 0.25f; private float m_fTimeAfterOneGroup = 0.0f; private float m_fTimeAfterCreate = 0.0f; private int m_nEnemyNum = 0; // Use this for initialization void Start ()
{ } // Update is called once per frame void Update ()
{ m_fTimeAfterOneGroup +=Time.deltaTime; m_fTimeAfterCreate += Time.deltaTime; if (m_fTimeAfterOneGroup > 2.0f) { if (m_fTimeAfterCreate > 0.25f) { GameObject clone = (GameObject)Instantiate(m_EnemyPre, m_CreatePoint.position, m_CreatePoint.rotation); clone.AddComponent("MoveScript_Shake"); m_nEnemyNum +=1; m_fTimeAfterCreate = 0; } if (m_nEnemyNum == MAX_GROUP_ENEMYS) { m_fTimeAfterOneGroup = 0.0f; m_nEnemyNum = 0; } } } } 敌机的移动脚本,可自己再定义新的移动脚本,在创建新敌机时挂上去就好:
using UnityEngine; using System.Collections; public class MoveScript_Shake : MonoBehaviour { //标志左右移动方向
private int m_nDir = 1; //原始位置
private Vector3 m_OriginalPos; //水平移动速度
public float m_HoriSpeed = 0.1f; //翻转速度
public float m_RotSpeed = 1.0f; //向前移动速度
public float m_MoveSpeed = 0.0005f; public Vector3 curScreenPos; public Vector3 LDPoint; // Use this for initialization void Start ()
{ m_OriginalPos = transform.position; LDPoint = GameObject.Find("LDPoint").transform.position; print (LDPoint); } // Update is called once per frame void Update ()
{ float relativeOffset = transform.position.x10) { Destroy(this.gameObject); } // print("Cur:"+transform.position); // if (transform.position.z < LDPoint.z) // { // Destroy(this.gameObject); // } } } 实现效果:
原来那个用Unity3D自带的火焰老改不出想要的效果,去看了一个教程,调出一个还好的感觉。
最后的效果是:
本文转自:http:///gameprogram/
第四篇:Unity3d射击游戏报告
Unity3D游戏开发
课程设计实验报告
项目名称 GoldCoinGame 班 级 11402 小组成员唐智 梁俊龙薛柯 高立存 姓 名唐智 学 号1404240717
1.游戏说明
游戏运行画面:
游戏目标:收集八个硬币,得到的硬币数量会显示在右上角。
游戏菜单:按esc显示,有三个选项:继续游戏,重新开始和退出游戏。
操作:WASD控制方向,12切换武器,r填装弹药,空格space跳跃。
步枪状态下: 鼠标右键——瞄准
手枪状态下: 鼠标右键——消音器
2.游戏素材来源:
1. 开火音效:手枪与步枪开火音效来源于课堂上的实验:Fps游戏中的MachineGun开火音效。 装弹音效:来源于网络。
2. SkyBox,水,Terrain的草地和椰树等来源于课堂上的实验:Survivalland。
3. 工厂模型Hangar_Full:来源于网络。
Cube的贴图:来源于网络。
4. 步枪和手枪模型及其动画:来源于网络。
5. 金币模型,塑料凳模型:使用3dmax软件自制。
6. 显示金币数量的CoinGUI的9张图片:采用Windows画图软件绘制。
3.Unity版本:
Unity 5.5.2f1 (64-bit)
4. 操作步骤
1.首先创建环境,CreatEmpty——Environment,将课堂上做过的水的预制体 DaylightWater放入到其下。
2.创建一个Terrain和三个DirectionalLight。
3.地形的凸起和凹陷操作界面
4地形的贴图操作界面
5.设置树木和草地。
7. 调整好光线角度,再把工厂预制体拖到小岛上。效果预览
8. 创建一个Empty,给它添加Capsule,MeshRenderer,CharacherController, 和Rigibody。(MouseLook和CharacterMotor以及Fpsinput均是课堂上使用过的例子,之后会用到)
9. 将Empty命名为MyFirstPersonController,将tag改为Player。把主摄像机移动到该目录下。
10.在摄像机maincamera下添加如下的Empty:weapon——m4a
1、handgun,用来存放武器。此外,再给camera添加skybox,选取合适的天空盒。
11.weapon添加一个js文件playerweapon,将步枪和手枪的预制体分别加到m4a1和handgun下。
Playerweapon.js主要控制武器的基本操作:开火,换弹和切换武器。 function Update () {
if (Input.GetButton ("Fire1")) {
BroadcastMessage("fire");//对子类发送fire的信息,从而达到调用所有名为fire函数的效果 }
if (Input.GetButton ("reload")) {
BroadcastMessage("reload"); }
if (Input.GetKeyDown("1")) {
BroadcastMessage("draw");//按1时播放动画 SelectWeapon(0); }
else if (Input.GetKeyDown("2")) { SelectWeapon(1); } } function SelectWeapon (index : int) {
for (var i=0;i
// Activate the selected weapon
if (i == index)
transform.GetChild(i).gameObject.SetActive(true);
// Deactivate all other weapons
else
transform.GetChild(i).gameObject.SetActive(false); }
}//切换武器的函数
12.给empty添加m4_preview,该文件主要负责步枪的子弹数量和开火音效播放,以及步枪的装弹。之后添加audiosource,选择开火的子弹发射音效文件。
13.添加一个UI----canvas,加入两个text,用来显示两把武器的子弹数目。
M4_preview的主要函数: function Update () {
GameObject.Find("/Canvas/Text").GetComponent(Text).text=" :"+ bulletsLeft+"/∞";//该函数可以将步枪子弹数量传递给text }
function fire () {
if (bulletsLeft == 0)
return;
if (Time.timeTime.deltaTime;
// Keep firing until we used up the fire time
while( nextFireTime < Time.time && bulletsLeft != 0) { GetComponent.().Play();//每发射一枚子弹,就播放一次开火的音效
FireOneShot();
nextFireTime += fireRate; }
Update ();//实现开枪后刷新text的子弹数量 }
function FireOneShot () {
var direction = transform.TransformDirection(Vector3.forward);
var hit : RaycastHit;
if (Physics.Raycast (transform.position, direction, hit, range)) {
// Apply a force to the rigidbody we hit
if (hit.rigidbody)
hit.rigidbody.AddForceAtPosition(force * direction, hit.point);
if (hitParticles) {
hitParticles.transform.position = hit.point; hitParticles.transform.rotation =
Quaternion.FromToRotation(Vector3.up, hit.normal); hitParticles.Emit(); }
// Send a damage message to the hit object
hit.collider.SendMessageUpwards("ApplyDamage", damage,
SendMessageOptions.DontRequireReceiver); }
bulletsLeft--;
m_LastFrameShot = Time.frameCount; enabled = true;
// Reload gun in reload Time
if (bulletsLeft == 0)
BroadcastMessage("reload");//没有子弹后自动装弹
}
function reload () {
yield new WaitForSeconds(1);//装弹等待时间
if (clips > 0) { //弹夹数量大于0时才可装弹
clips--;
bulletsLeft = bulletsPerClip;
}
Update ();//装弹完成后更新text显示的子弹数量
yield new WaitForSeconds(1); }
14.步枪的预制体m4animation,m4.js主要负责步枪的开火、装弹等动画播放。 给它添加一个audiosource,选择下载的武器换弹音效。
15.手枪的步骤和步枪类似,就不在阐述,不同处如需要修改开火的速率(firerate)等参数即可。
16.添加两个武器的贴图到显示弹药的text的左侧,再添加一张背景图,调整好位置后效果如图:
17.添加菜单:在canvas中添加一个panel,在panel下添加三个button,分别对应退出,重新开始和继续,再添加一个text,内容为 “已暂停”。
18.添加一个empty命名为_GM,给他添加Manager.cs,一个负责菜单的文件。
其主要部分如下:
void Start () {
UIPanel.gameObject.SetActive(false); isPaused = false; }
void Update () {
if(Input.GetKeyDown(KeyCode.Escape) && !isPaused) Pause();
else if(Input.GetKeyDown(KeyCode.Escape) && isPaused) UnPause(); }
public void Pause() {
isPaused = true;
UIPanel.gameObject.SetActive(true);
Time.timeScale = 0f; }
public void UnPause() {
isPaused = false;
UIPanel.gameObject.SetActive(false);
Time.timeScale = 1f; }
public void QuitGame() {
Application.Quit(); }
public void Restart() {
Application.LoadLevel(0);
}
主要负责对应菜单的按钮的功能
之后,给三个按钮加上相应的贴图和文字,在OnClick一栏中,选择_GM,
在右侧下拉选择之前manager中对应的函数,比如退出游戏的Quit按钮就选择QuitGame。 另外,编辑Panel的image,可以更改菜单的背景图片。
效果如图
19.建立cube的预制体:创建一个3dobject,建立一个cube,再放在预制体的文件夹perfabs里,再更改cube的贴图为黑色,命名为cube_dead,同样拖入perfabs中。
给预制体cube添加一个DamageReciver,使它能接收到子弹的伤害,从而从cube转换成cube_dead。
同时,勾选中iskinematic,让这个预制体被子弹击中前不受到里的影响,这样可以把cube悬空而不掉落,而变成cube_dead则会掉落。
20.把制作的coin模型导入,添加刚体,同样勾选iskinematic,并加入CapsuleCollider,勾选isTrigger,最后关联Coin.cs。
void Update () {
transform.Rotate (new Vector3 (rotationSpeed * Time.deltaTime, 0, 0)); }
void OnTriggerEnter(Collider col) {
if (col.gameObject.tag == "Player") {
col.gameObject.SendMessage ("itemPickup"); Destroy(gameObject); } }
分析:
硬币没被拾取时,会沿着x轴旋转
玩家触碰到coin时,会传递一个信息itemPickup,提示该硬币已经被拾取,之后会销毁该硬币。
21.回到第一人称控制器,给MyFirstPersocontroller添加脚本item, 选择金币拾取音效、拾取贴图。创建并添加提示文字GUItext。
创建一个empty命名为CoinGUI,添加guitexture,选择image为coin0,即没有失去硬币时候的显示图。Coin到Coin8依次对应获得八个硬币的显示图。
22.准星的添加:创建一个empty,添加crosshair脚本,将网上下载的准星贴图添加进来。
大致的步骤就如上所述。
小组成员:唐智
主要负责部分:武器模块和esc菜单模块以及实验报告的编写。
武器的部分是由我制作的,相对于我们课堂上制作的火箭筒和步枪,这个项目里面多了reload这个动作,并且是可以主动按r来reload的(课堂上的项目只能打空弹匣来换弹)。
开始时,我在原来的脚本基础上修改代码,想把调用动画的代码也写进计算子弹fire和reload的代码中,但是出现了很多问题:如动画不能正常播放、或是播放了动画不开火等。
最后,我将这两个部分的脚本分开到两个目标上,解决了这些问题。 第二个小问题,就是装弹后子弹数量没有实时更新到text里面,但是开火后子弹数量会重新刷新。这个问题通过在reload函数末添加了显示子弹数的代码后解决。
这次在原来的游戏基础上新添加了esc菜单这一功能,脚本使用c++编写。 在操作完后要注意的是需要完成File—buildsetting—add openscenes 这样才算是完成,因为 Application.LoadLevel(0);这句代码中的0就是代表着我们add的这个场景位于第一位,这样restart按钮才能进入到这个场景的初始阶段,达到重新开始的目的。
第五篇:unity3d游戏开发之登录注册应用
在注册的时候,输入了数据库已存在的用户名,会显示用户已存在。
//验证用户是否存在
Users u = new Users().register(name);
if (name == u.Name)
{
name = "该用户已存在";
a =GUI.Button(new Rect(600, 360, 40, 20), "注册");
}
在登录的时候,当用户输入错误密码或用户名就会出现提示:
章来自狗刨学习网
代码部分:
如果用户名和数据库的不同
就提示:
print("用户或密码错误");
name = "";
password = "";
flag = true;
这篇文章来自狗刨学习网
这篇文