Unity3D游戏开发笔记4.docx
- 文档编号:6167467
- 上传时间:2023-01-04
- 格式:DOCX
- 页数:51
- 大小:1.46MB
Unity3D游戏开发笔记4.docx
《Unity3D游戏开发笔记4.docx》由会员分享,可在线阅读,更多相关《Unity3D游戏开发笔记4.docx(51页珍藏版)》请在冰豆网上搜索。
Unity3D游戏开发笔记4
2014.1.26
10.【边界与优化昼夜系统...崩溃的Unity!
】
(1)今天该做什么了呢?
先把地图几个边界吧。
虽然这不是必须的,不过为了玩家的生命财产安全,我觉得加上应该是必要的。
新建一个立方体,把它放大到合适的位置,然后放在地图边界上,比例差不多了,就可以把它拖放到以前建立的_MyPrefab中。
然后复制三个,分别放在))四个边界上,就可以了。
如图:
最后只要把方块的渲染选项的勾去掉,让它看不见即可。
(2)然后吧,就把昼夜系统再完善下。
在当初写昼夜系统的时候,如果到了晚上,是直接把平行光的角度往上转,虽然这样达到了将场景弄到夜晚的目的,但是因为这样的原因是由地形挡住造成的,所以地面会有一些高光,导致晚上的场景看起来不但假,也不好看,还极度浪费资源。
这里就得改一下。
方式也不难,就是在DayAndNightManager脚本中,在改动平行光角度的switch语句里,将“黎明”至”晚上“的判断语句的break前,加上这么一句:
m_tramsform.light.type=LightType.Directional;
而在”晚上”至“黎明“之前,都加上一句改变灯光类型为点光源的:
m_tramsform.light.type=LightType.Point;
虽然在这儿其实在各个关键点换一下灯光就可以了,不过考虑到往后肯定会有直接改变时间的时候,未免出现bug,这里就麻烦点,不去省资源了(也省不了多少)。
到了晚上,阴影一去,drawcall这下子降了近一半。
资源省惨了~~。
(3)这儿,本来应该是写今天刚做的物品栏之类的,可惜,电脑在休眠中断了一次电,什么都没了......
除了脚本,地图全变成了空的!
我能说什么了?
而且还什么预设都没存,这下.....被坑得好惨啊!
欲哭无泪啊555.。
。
。
恐怕只有重做了......幸好代码还在!
555......
2014.1.27
11.【新的开端与角色暴击...GUI浮动提示栏。
】
又再次搞了一天,弄出了这么个模样:
不多说了,说多了就是泪.....
在这儿写是因为想提点一下:
绝对不能把整个daikonGUI的UI做成预制体,否则Unity直接崩溃没话说
.....刚又折腾了个小时才找出这么个原因!
以前丢失的都是些地图,幸好与大局无碍。
而且刚才测试的时候又发现了一个Bug,就是如果敌人直接被Destroy掉的话,刷新点就会因为判断没有重置而一直不再刷新(就像是上面那个平台,敌人掉下去就被Destroy了,刷新点却一直不刷敌人了。
)
修复的方法很简单,就是在EnemySpawn脚本中,
if(m_madeEnemyState!
=null)
{
m_madeEnemyIsDead=m_madeEnemyState.m_isDead;
}
后面加上一句重置敌人没有刷出的判断:
if(m_madeEnemyState!
=null)
{
m_madeEnemyIsDead=m_madeEnemyState.m_isDead;
}elsem_madeEnemyIsDead=true;
这下就可以了!
现在的话,还是先给玩家角色增加一个属性:
“暴击率”吧。
不然,光是敌人有暴击攻击,就不大公平了。
打开PlayerControl脚本,在最开始的属性标签中新定义一个属性:
publicfloatm_bigAttack=0.02f;//暴击几率
同时,在对象标签中分别定义一个暴击的粒子效果和音效:
//粒子效果
publicTransformm_attackParticle;//普通攻击粒子
publicTransformm_bigAttackParticle;//暴击粒子
//声音
publicAudioClipm_attackAudio;//普通攻击音效
publicAudioClipm_bigAttackAudio;//暴击音效
最后就是在下面的攻击过程中进行暴击的判断,将Attack函数中关于攻击的判定改成这样:
if(Input.GetMouseButtonDown(0))
{
if(m_attackDelay<0)
{
if(Random.value>m_bigAttack)
{
m_animation.Play("Attack3-1");
m_forward=m_transform.TransformDirection(Vector3.forward);
//Debug.DrawLine(m_transform.position+Vector3.up,newVector3(10,0,0),Color.cyan);
if(Physics.Raycast(m_transform.position+Vector3.up,m_forward,outhit,2,m_layerMask))
{
m_nowAttackTarget=hit.collider.gameObject.GetComponent
StartCoroutine(WaitForAttack("Attack3-1",0.65f,m_attackParticle,m_attackAudio,m_attack));
}
}else
{
m_animation.Play("Attack4");
m_forward=m_transform.TransformDirection(Vector3.forward);
if(Physics.Raycast(m_transform.position+Vector3.up,m_forward,outhit,2,m_layerMask))
{
m_nowAttackTarget=hit.collider.gameObject.GetComponent
StartCoroutine(WaitForAttack("Attack4",1.8f,m_bigAttackParticle,m_bigAttackAudio,m_attack*2));
}
}
m_attackDelay=1;
}
}
我默认的暴击攻击力是普通攻击力的2倍。
然后将暴击音效和暴击粒子效果赋给角色,就可以了。
就是这样。
接下来,我将最下边的那条技能栏取消了,改成了显示几个属性:
这个是比较简单的。
首先在原来技能栏的地方建立一个Panel,用于装玩家的几个属性,里面先新建
一个Label,用来显示攻击力,所以我将字体颜色改为了蓝色,并将其命名为attack。
Anckor设置为Left和Vertical。
然后添加一个数据Binding,数据源为玩家角色的PlayerControl中的m_attack,目标为自身的Text:
依样复制四个,放在合适的位置,数据绑定只需要改为相应的值即可。
分别是:
防御、速度和暴击。
这些做完了,然后呢,就给它们加上一些ToolTips吧。
效果就是当鼠标放在上面的时候,可以浮现一小行说明性的文字。
这就是传说中的ToolTps!
看起来可是挺牛的!
研究研究了半天,我发现这里DaikonGUI官方的例子已经自带了,而且貌似还可以直接用。
打开DaikonGUI的ToolTip例子,将GUI中的那个ToolTip直接拖到先前创建的_MyPrefab文件夹中,做成一个预制体,然后回到先前自己的地图,将这个“ToolTip”拖拉到DaikonGUI的UIroot下,如图:
然后再在先前创建的几个属性Label中,找到appearance下的ToolTip将各自需要显示的内容直接写上去,如图:
现在运行游戏的话,将鼠标放在下面的属性栏中,一会儿就会浮现出属性的说明。
如果嫌他慢的话,还可以更改下时间以及动画速度。
效果如图:
现在,尽情地写上提示吧!
认为不错的地方,都可以加上了。
今天就到此为止吧。
2014.1.28
12.【GUI之...物品窗口】
现在的话,终于该继续前天被残忍打断的物品栏之类的GUI界面了!
首先还是把“属性”、“物品”、“技能”、“系统设置”几个按钮放上去罢。
我是这样设计的:
美工方面确实不是俺的长处,资源也都是用的DaikonGUI自带的。
新建一个Panel,用于盛放这几个按钮,Anchor设置为Right和Bottom即可。
然后再将这个Panel命名为“MyBottomBar”,在这个Panel中新建四个按钮,放上相应的图标即可。
如果为了好看点,还可以设置Havor状态的显示,我就设置了一下Havor状态的颜色。
它们的Anchor都设置为Right和Verticle。
名字根据相应的作用,分别命名位为:
Bag、AttibuteWindow、Skill和System。
在这里,还可以在相应的ToolTip中输入相应的提示语句:
然后吧,就先来做物品栏吧。
再屏幕中选择一个合适的空白处,点击新建一个Panel,背景设为FantasyAtlas中最像窗口的图片,然后再在这个Panel中添加一个DragHandle,在DragHandle中新建一个Label,内容就是“物品”。
因为这是个窗口,所以也可以再为其添加一个ResizeHandle,使其可以拖动改变大小。
如图:
然后再为其中间添加一个ScrollPanel,作为显示物品的主窗体,最下面添加一个Buttom,选择合适的图片,并写上“关闭”两个大字:
接下来,在中间的物品窗口右边,添加一个ScrollBar,Anchor为Left和Verticle即可。
在这个ScrollBar之中,分别建立两个Sliced图片,并命名为Track和Thumb,最后将这两个图片拖到ScrollBar上,即可完成ScrollBar的建立。
最后再把这个ScrollBar拖给中间的ScrollPanel的Verticle滚动条,即可。
其中我还设置了一些窗口的Layout:
窗口大体创建出来了,下一步,就是为打开和关闭这个窗口添加功能以及一些动画了。
动画事件之类的都是添加在主窗口之上。
首先为其添加一个Tween中的Vector2,这个用于改变其大小,只需要在EndValue点击“Assigncurrentvalue”即可。
然后是改变位置的动画。
添加一个Tween中的Vector3,选择“RelativePosition”,先点击一下EndValue中的“Assigncurrentvalue”,然后把窗口移动到右上角,再点击StartValue中的“Assign.....”,这样就记录这个动画了。
如图:
最后的话,因为包裹按钮只有一个,为了方便,在这里还可以添加一个“TweenGroup”。
为Group添加两个Item。
将先前添加的两个Tween动画都拖进这个组,如图:
然后,就是包裹按钮方面的了。
点击先前做好的包裹按钮,添加一个EventBinding(事件绑定),数据源为自身被点击,而目标事件就是先前的TweenGroup脚本中的Play:
这下子运行游戏的话,点击包裹图标,就会看见物品窗口从屏幕外飞进来。
然后是飞出的动画,这个弄一个位置变化的动画就行了吧。
再次为主窗口添加一个Tween动画中的Vector3动画,命名为FlyOut,然后在StartValue记录屏幕中的当前位置,然后把窗口远远拖动到左边看不见的位置,记录EndValue。
然后为窗口中的关闭按钮添加一个EventBinding,事件为点击按钮,目标则是窗口播放TweenVector3中的FlyOut的动画。
运行游戏,点击包裹,窗口将会从右上方飞进来,点击关闭按钮,窗口则会从左边飞出去。
这个窗口的界面因素就差不多了。
然后,下面就又到了脚本时间了!
包裹GUI终于把数据同步的问题解决了!
不过现在不是一丁半点地晚了,具体情况还是明天记载罢。
唉。
2014.1.29
13.【GUI...完成物品窗口】
希望我没把昨天的具体步骤记错.....!
0-0!
那么就开始吧。
从哪儿开始写起呢?
先从Item这个脚本开始吧。
Item脚本建立在_Script/GUI文件夹中,打开脚本,最开始定义了几个变量:
#region定义的对象
publicGameObjectm_itemButton;//物品的GUI按钮
privateBattleChangem_playerState;//玩家的BattleChange脚本
privatedfScrollPanelm_itemPanel;//物品窗口
privatedfButtonm_button;//物品按钮的脚本
#endregion
#region治疗类物品
#region小血瓶
publicstringm_littleLifePotion="小血瓶";
publicintm_littleLifePotionNumber=0;//数量
publicintm_littleLifePotionPrice=10;//价格
privateboolm_littleLifePotionAdd=false;//是否已经在面板中创建了物品
publicstringm_littleMagicPotion="小蓝瓶";
publicintm_littleMagicPotionPrice=13;//价格
publicintm_littleMagicPotionNumber=0;//数量
#endregion
#endregion
因为没有打算再把道具之类的弄个图片显示,所以就没再定义Texture了。
毕竟再定义一张图片不但麻烦,而且也不一定有人“赏识”的,所以这儿我就用纯文字了。
以上定义了两个物品,分别是小血瓶和小蓝瓶,现阶段也只有这两个物品了。
都有具体的注释,这里就不多解释了。
然后是Start函数中,我分别获取了玩家状态和物品窗口的具体对象(在这之前要新建一个名为“ItemPanel”的tag,然后将其指定给物品窗口):
m_itemPanel=GameObject.FindGameObjectWithTag("ItemPanel").GetComponent
然后接下来是一个自定义函数AddButton,这个函数将负责物品按钮在物品窗口中的创建,以及判断是否应该显示物品按钮(如果物品数量小于零,也就是没有时,就不需要显示在窗口中了。
):
voidAddButton(stringname,intcount,stringdescribe,refboolifAdd)
{
if(!
ifAdd)//如果物品没有被添加到按钮
{
m_button=m_itemPanel.AddPrefab(m_itemButton).GetComponent
m_button.Text=name;
m_button.Tooltip=describe+"("+count+"个)";
ifAdd=true;
}elseif(count>0)
{
m_button.Tooltip=describe+"("+count+"个)";
m_button.IsVisible=true;
}else
{
m_button.IsVisible=false;
}
为了减少以后的劳动力,使代码的复用性最高是必要滴。
代码主要作用就是接受物品的名字、数量、描述信息以及是否在物品栏添加了按钮的几个参数,如果没有在物品窗口添加按钮,则添加物品按钮,并设置好物品按钮的名字、描述信息。
如果物品按钮已经被添加在了物品窗口,那么就判断物品数量是否大于零,大于则显示出来,否则就隐藏掉按钮。
(按钮预制体会在以后创建,其实我是先创建的预制体....)。
接下来还是一个自定义函数UseItem,这个函数是给玩家按下按钮后,进行使用物品而建立的,由于现在只有两个物品,代码不多:
publicvoidUseItem(stringname)
{
switch(name)
{
case"小血瓶":
if(m_littleLifePotionNumber>0)
{
m_playerState.RecoverLife(100);m_littleLifePotionNumber--;
}
break;
case"小蓝瓶":
if(m_littleMagicPotionNumber>0)
{
m_playerState.RecoverMagic(50);m_littleMagicPotionNumber--;
}
break;
}
}
这个函数其中调用了两个玩家BattleChange脚本中的两个函数,所以现在还必须为BattleChange添加这两个函数。
打开BattleChange脚本,因为恢复函数中还用到了最大魔法值,所以先在最开始添加一个变量:
publicintm_maxMagic;//最大法力
然后在PlayerControl脚本的Start函数中将m_maxMagic赋值过来,就可以在最后边添加两个恢复函数了(这里用恢复函数若不是直接去增加生命值,是考虑到恢复的提示,以及判定等原因的):
publicvoidRecoverLife(intlife)
{
m_life+=life;
if(m_life>m_maxLife)
{
m_life=(int)m_maxLife;
}
m_dfTxet.Text+=("
}
publicvoidRecoverMagic(intmagic)
{
m_magic+=magic;
if(m_magic>m_maxMagic)
{
m_magic=m_maxMagic;
}
m_dfTxet.Text+=("
}
函数首先添加指定的生命或法力值,然后判断了添加后的生命或法力是否超出了最大值,如果超过了最大值,则将将其重置为最大值。
并给出恢复的提示。
然后吧,事情要一步步来,那么现在先把预制弄体好。
在物品窗口中点击新建一个Button,命名为ItemButton,将Button的Anchor全都去掉,(不去掉的话,可能会产生一些奇奇怪怪的格式...),其它的话,再在文字设置那儿将WordWrap勾选了即可。
而上一层的物品窗口,也要设置勾选了AutoLayout等才行。
如图:
将做好的按钮拖到_MyPrefab文件夹中,做成一个预制体,然后再_Script/GUI问价夹中继续新建一个脚本,这个脚本用于处理点击了物品按钮之后对物品的使用函数的调用。
命名为ItemButton。
代码如下:
usingUnityEngine;
usingSystem.Collections;
publicclassItemButton:
MonoBehaviour{
privateItemm_item;
privatedfButtonm_button;
privatestringm_itemName;
voidStart()
{
m_item=GameObject.FindGameObjectWithTag("ItemPanel").GetComponent
m_button=GetComponent
m_itemName=m_button.Text;
}
publicvoidUse()
{
m_item.UseItem(m_itemName);
}
}
这个脚本首先获得该按钮的名字,以便调用Item脚本中的UseItem函数,在Start函数中获取了组件后,然后自定义一个函数Use,Use函数就只有一行代码,就是使用按钮的名字去调用Item脚本中的UseItem函数。
现在,将Item函数拖动到ItemPanel,也就是物品窗口上,ItemButton脚本拖放到ItemButton按钮上(物品按钮),然后点击ItemButton,添加一个EventBinding,数据事件为按钮Click,目标的是ItemButton脚本中的Use函数。
然后点击物品按钮上的Apply,将改动同步到预制体上。
这时就可以把ItemButton的预制体拖给ItemPanel上的Item脚本了。
运行有游戏,差不多就是那么回事儿了。
实测。
。
。
。
。
问题还是有的......
这样做的话,除非只有一个物品,否则会出现按钮数据显示根本不准确的问题,甚至点击按钮作用都反了!
简直不敢相信这样东西多了该怎么办?
所以,又改吧。
初步分析,出现上述情况原因是当Item脚本中的AddButton函数在Update中调用时,第一次调用肯定是对的,但架不住Update不停的调用啊!
.....好吧,我说重点。
因为每帧都在对AddButton函数进行调用,但先前使用的每一个物品按钮的对象都来自一个对象:
那就是定义在最开始的privatedfButtonm_button;//物品按钮的脚本,我原本准备让这个按钮对象充当所有物品的按钮对象的...临时变量,.....直接结果就是,他果然变成了临时变量,以至于当第一个物品赋值完毕后,它所应当存储的变量就没了,那么首先第一次建立的按钮还能对其进行正确的赋值吗?
答案当然是否定的,所以就出错了.....
改造方法就是每个按钮都使用单独的对象来存放.....果然还是不能偷懒是吧...?
首先将最开始那个m_button对象注释掉,然后再在小血瓶和小蓝瓶中,分别定义两个Button对象,这儿我想到使用一个判定按钮对像是否为空的方法来判断按钮是否被创建了,所以在这儿的判断按钮是否被创建出来的bool变量也可注释掉了:
#region治疗类物品
#region小血瓶
publicstringm_littleLifePotion="小血瓶";
publicintm_littleLifePotionNum
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Unity3D 游戏 开发 笔记