1.代码提示问题
打开preferences→extemal tools
2.在window中可以打开自己想要的面板
可以自由拖放自己的面板,然后在layout保存自己喜欢的布局
一般用tall,然后调整一下project
3.后期导入的模型跟音效都会保存在Assets里
4.创建项目后项目名称带*,说明项目没有保存
5.快捷键
复制 :ctrl+D
聚焦物体 :F
环绕查看:Alt+鼠标左键
步移工具:ctrl
修改名称:F2
注释:Ctrl+K
取消注释:Ctrl+U
自动吸附顶点:V
在视野的模式下:按Q键向下,E向上,W向前
6.旋转
Local围绕自身轴旋转
Gobal围绕空间轴旋转
(Local自身坐标系,Gobal全局坐标系)
Transform中的Rotation表示旋转度数,Scale表示缩放
7.pivot建模原点;center中心
8.使用步移工具,必须要切换到Global状态
9.每个游戏角色都有自己名字,F2修改名称
10.smoothness光滑程度
11.mesh网格;Mesh Runderer在网格上渲染
12.建模一般建两种,一种精细化用来渲染,一种是简模,用来做碰撞检测
13.发生碰撞效果,添加“刚体组件Rigidbody”
script创建脚本(脚本也是一种组件,可以通过创建/删除组件来控制)
14.C#script中,如"public class Player"中的Player,后期就算修改要记得跟运动物体保持一致
15.注释:Ctrl+K、Ctrl+C
取消注释:Ctrl+K、Ctrl+U
16.如何使刚体组件与具体的一个运动物体连接,有两种方法:
1.在代码中更改,=在算法中相当于赋值:如rd=GetComponent<什么类型的组件如Rigidbody>();刚体是模拟物理效果,我们要给他施加力才能运作起来,在update中给施加持续的力,如:
rd.AddForce(力的大小跟方向如Vector3.right);
2.拖拽的方式 :将Player拖拽到组件rd的位置,但拖拽容易出现引用丢失的情况。如果有两个刚体组件的话,会以代码指定的为准。
17.代码中的public/private:组件中的属性可以是公开的,也可以是私有的,一般只把必要的属性设置为公有的。如果设置为私有的就没办法通过拖拽设置值了。
18.向量:forward、Left、back、right
19.监听键盘按下:float h = Input输入,GetAxis得到轴("Horizontal"水平轴) ,h是一个小数的意思。点击播放按钮,小球落下,点击图形界面,按键A,看到Consale里从0→-1的变化。Debug.Log(h);→rd.Addforce(new Vector3(h,0,0))l;注:vector中的h如果赋不上值,可以复制前面的内容。键的控制快捷键可以通过Project Settings→Axes中修改;player的运动速度可以通过rd.AddForce(new Vector3(h, 0, v)*1);*1代表速度
20.控制相机跟随小球移动:在Camer中添加脚本→计算两个位置的差→Vector3 offset(偏移)=transform.position(自身的位置)-(小球的位置)playerTransform.position;
小球的位置怎样获得?输入属性:public Transform playerTransform;然后回到界面,打开Camer,把player拖拽到Camer中的Script
设置主相机的位置:transform.position=playerTransform.position+offset;(注:offset下方有波浪线,因为offset是在start方法里面定义的,所以在update里面是没有办法使用的,解决方法:输入private Vector3 offset;
21:添加墙:创建Cube→positon设置Y:0.5
Scale中的Z为20。创建材质、附材质。复制墙Ctrl+D,将四周都围上墙。
22.预制体:地面等都属于环境:创建一个空物体命名为Env,将环境相关的物体都拖到Env下面。创建预制体:预制体相当于一个模板,在Assets下创建一个模板文件Prefabs,如:创建一个方体作为Food,将方体放入Prefabs文件中作为一个预制体,可以直接Ctrl+D复制,例如Food(1)作为Food的孩子,修改预制体Food其他孩子也会变化,如果修改Food(1)想让Food发生变化的话,将Food中的Overrides修改为Apply all,这样母亲Food连同其他孩子都会被修改。(注:当一个物体被旋转后再使用移动工具,坐标轴会跟物体坐标轴一致,这时可以打开Gobal模式,就可以跟世界坐标轴一致了。)
Prefab 预制体
Instance 实例
Class 类
Instance (对象-Object)实例
23.控制小球旋转:给Food预制体创建一个脚本→tansform.Rotate旋转(Vector3.up);
24.查文档:在Help:Unity Manual,Scripting API→Class类(文档当作字典查阅的)(UnityEngine→Class)
25.碰撞检测:在player写一个系统事件(如start、Update都是系统事件),写oncollisionEnter,会自动给出系统事件,输出(Debug.Log("发生碰撞了")),碰撞一共有三个阶段,oncollisionEnter,oncollisionExit,
oncollisionStay,如果物体碰撞之后player会把food吃掉,就不需要执行Exit、Stay方法了。
区分Food的方法:名字/标签,但是名字跟标签都可以重复,给它添加标签Add Tags,修改Prefabs里的标签,所有的Food都有标签了。
collision.gameObject.tag(碰撞到游戏物体的标签)
条件编程语句:用来判断碰撞物体条件if(collision.gameObject.tag=="Food")→
Destroy(collision.gameObject);
(解释:是先通过collision再到gameObject,然后再找到标签的)(注意:赋值时用的是==而不是=)
标签获得:可以通过游戏物体获得标签,也可以通过组件获得标签。即一个为collision.gameObject.tag
collision.collision.tag
26.通过触发检测,吃东西:触发检测是可以不发生碰撞效果就可以吃东西,只要进入触发检测的范围内。
创建一个Cube,然后给一个标签test,将Cube里Box Collder中的is Trigger勾选。触发检测也有三个过程,OnTriggerEnter;OnTriggerExit;OnTriggerStay;
If(other.tag=="Food")
Destory(other.gameObject);
然后将Food的碰撞器修改为触发器。
27.通过UI显示得分:
1.首先给定义一个整数变量:public int score=0;(int:整数 score:变量)
score++:++是自增运算符。
2.创建UI:Button按钮,Text文本,Image图片;创建一个Text,切换到2D模式,双击Canvas(画布,Evensystem事件系统),调整text组件(1.调整字在框中的位置及,居中 2.调整小框在大框中的位置,按着Alt+右上角的键,可以自动对齐右上角3.调整字体大小.)
3.将数字计算(score)与UI关联:
引入UI的命名空间:using UnityEngine. UI
定义一个组件:public text scoreText;
将Text拖拽到Score Text下面,这样Player就可以有访问UI组件的权限了。
分数发生变化时要更新UI显示:
scoreText.text="sdfaesd";(字符串的含义是,把sdfaesd给UI,即UI显示sdfaesd,如果是显示分数的话,应改为scoreText="分数"+score;
28.显示游戏胜利:创建一个UI,text,(为防止后期text混乱,给每个text重新命名,ScoreText,WinText),把wintext禁掉,等游戏胜利了再激活wintext。
1.首先给一个游戏物体的引用:
public GameObject wintext;
在if(other.tag=="Food")下面给If(score==12)
{ winText.SetActive(true);(解释:true/false,SetActive激活,是否激活)
29.游戏打包:File→BuildSetting→addopensence
然后在unity Hub中安装程序用来打开游戏
如果是PC端导出,选PC,点击Build,创建
默认是全屏状态下运行,如果改成窗口状态下运行:Player Setting→resolution(分辨率)
→window(窗口模式)→创建
案例2:打砖块
1.创建地面、墙体:创建MineScen→创建Plane→reset使地面位于中心部分→改名ground→创建Material→附材质;建墙体Cube→Y0.5重命名Brick→创建Prefab文件夹→将Brick拖到Prefab里→复制墙体→步移(按着Ctrl移动,就会根据步长,移动步长是可以设置的,在左上角Scene窗口里)→选择复制6排高→选中墙块 右键创建Empty parent
2.控制相机移动:给相机加一个Script→
movement→transform组件用来控制自身的位置、旋转、大小→Transform.translate(变换的方法)(Vector3.Left);
(注意:我们在使用某个组件的时候,是先使用某个组件如Transform,再使用这个组件上的某种方法如Translate的)
用wasd来控制相机方法:首先给相机一个水平轴:float h=Input.GetAxis("Horizontal");
transform.Translate(new Vector3(h,0,0));
相机移动过快解决:update的更新次数→创建一个Script命名为LearnUpdate→Debug.Log(Time.deltatime);
Debug.Log(1/Time.deltaTime);
(FPS:每秒可以执行多少帧,成为延迟)
∵运动距离=速度*时间
∴Transform.Translate(new Vector3(h,0,0)*Time.deltaTime);(这里的Vector3代表着在x轴运行的一个速度)
如果想以两倍的速度移动相机:
Public int speed=1;
∴Transform.Translate(new Vector3(h,0,0)*speed*Time.deltaTime)
再给相机一个y轴方向的移动
float v=Input.GetAxis("Vertical");
(注:写代码习惯性将方法首字母大写,属性首字母小写)
Update更新次数是不确定的,但FixedUpdate更新次数是固定的,也可以设置,在ProjectSetting中可以设置执行间隔时间
3.发射小球:创建一个球体,Bullet,将其放在Prefab里→在Camer身上添加一个新的脚本Shoot:定义一个Prefab:
Public gameObject bulletPrefab
(可以是场景中的某个物体,也可以是个Prefab)
//根据Prefab创建实例=实例化Prefab
GameObject.Instantiate实例化(bulletPrefab.transform.position,
transform.rotation);(position,rotation代表相机的位置)
当我们按下鼠标左键的时候再去实例化,怎样检测按键?如下:
跟按键有关的都是通过Input输入的
Input输入.GetMouseButtonDown(0)
(0代表左键,1代表右键)
if(Input.GetMouseButtonDown(0))
{GameObject.Instantiate(bulletPrefab.transform.position,
transform.rotation)};
如果想让物体有物理效果要添加刚体组件
在bullet下添加Rigidbody,方法:
1.获取刚体组件2.给它施加力
if(Input.GetMouseButtonDown(0))
{GameObject bullet=GameObject.Instantiate(bulletPrefab.transform.position,
transform.rotation)};
rigidbodyrd=bullet.getcomponent<Rigidbody>();
rd.AddForce(Vector3.forward*100);
(100代表100N的力)
(GetMouseButtonDown,代表鼠标按下)
∵当通过力的方式给它速度,没办法直观看到给的力的大小及转化成的速度
∴这里可以通过给速度的方式
rd.velocity=Vector3.forward*30;
(forward向前的力)
给墙一个物理效果rigidbody
Unity中资源的导入方式:
Asset Store资源商店里有→下载好资源→拖拽到unity中/右键import package
unity自带的资源导入:打开unity安装文件→unityDownloadAssitant→standard Assets→安装在unity的目录下
添加窗口:在菜单栏的空白处右键,addTab
Layer可以控制层:锁定、隐藏
maximize;最大化游戏窗口
聚焦某个物体:1.双击物体2.按F键
Transform组件:position.rotation.scale;reset重置值
V工具可以吸附顶点:方便顶点对齐
预制体属性:创建一个Cube→拖到Assest里变成一个预制体→Ctrl+D复制两个,修改其中一个的属性,其余两个不变→如果想让其变回最原始状态可以选择reset,变成预制体的状态可以选revert;
案例3:古迹探险
古迹地形设计:创建Terrain:地形设计
Terrain Height:最大高度
创建一个Terrain的文件夹,将TerrainDate放入
笔刷:1.刷到最大高度就不会再变大了
2.地形还原:按shift+笔刷,Opacity可以控制笔刷的程度。
3.添加贴图:在笔刷选项下→rise or lower Terrain→paint Texture
4.导入树:Tree→speedtree→可以导入树
5.刚体组件:选择相机→Align with view相机跟当前视野保持一致→小球→rigidbody
Drag:摩擦力(既会增加下落的阻力,也会增加在地面的阻力)
Angular Drag:旋转时候的摩擦力
Use Gravite:是否使用重力
Freeze Position:冻结坐标轴
Freeze Rotation:冻结旋转轴
Mass:物体的质量:影响物体运动的惯性
碰撞器:
Terrain Collider:如果地形碰撞器容易出现错误,我们给添加一个Box Collider,调节至跟地面贴合
Mash Collider:会比较费面,耗性能,碰撞更精准,根据面的多少来看
Mash Renderer:针对不太精准的碰撞,且面比较多的情况,这个碰撞器就可以
碰撞检测:如果选sphere,就是检测在shpere身上发生的碰撞,如果选cube就是检测在cube身上发生的碰撞
创建Script→指定给Sphere
oncollsionEnter、OncollsionExit、OncollsionStay
(注意:两个物体发生碰撞的前提是有碰撞器collider,其中一个或两个都有刚体rigidbody)
经过测试: OnCollisionEnter方法被触发要符合以下条件
1 碰撞双方必须是碰撞体
2 碰撞的主动方必须是刚体,注意我的用词是主动方,而不是被动方
3 刚体不能勾选IsKinematic
4 碰撞体不能够勾选IsTigger
触发检测:小球可以穿过检测物体,不发生碰撞。创建Cube中BoxCollider中的Is Trigger,取消勾选Mesh Render或者将其移除
OnTriggerEnter、OnTriggerExit、OnTriggerStay
print("OnTriggerEnter:"+other);
(other会直接输出触发器的名字)
print("OnTriggerEnter:"+other.name);
(.name可以获取触发器所在游戏物体的名字)
print("OnTriggerEnter:"+other.tag);
(.tag可以获取触发器所在游戏物体的标签)
要注意ontriggerEnter方法写的位置,不要写在大括号内部
灯光:右键创建PointLight、arealight区域光
火焰:windows→Lighting→Settings
烘焙:将含有地形的Env文件选择Static,Light也勾选Static,Terrain也勾选
再去lighting中,点击General Lighting生成光照贴图Generate Light生成光照贴图→禁用灯光检查是否烘焙上(场景变得无灯光效果就是没有烘焙上)→没有烘焙上,选择灯光→Mode选择Baked→再把灯光启用→再进行烘焙→再把灯光禁用后依旧有灯光的效果
在火光的灯光效果中:Mode选择Mixed,因为火光需要一闪一闪的效果,因此需要计算
火光:(在这之前创建灯光时将灯光放入Perfab文件,方便后期Apply all)创建Particle systerm→调整速度→粒子样式open Editor→可以选择导入的fire
shape:调整火焰形状
Start Lifetime:火焰大小控制
Start speed:可以调整为Random between two contents两个数值控制速度
size overLifetime:修改火焰大小渐变
Rate over Time:火焰数量
Radius:火焰聚拢
粒子样式:找到火焰贴图所在的位置→创建Material→命名为flame→如下图创建好材质后→导入Rander中作为贴图
(1)Renderer模块
设置其Material,将火焰粒子贴图放入其中。
(2)Texture Sheet Animation模块
由于火焰贴图共有4帧,因此需要将其水平和垂直方向的平铺数量划分成2,设置Tiles的x和y为2。
(3)shape模块
radius设置为0,使得粒子产生的位置固定。
Force over Lifetime模块
粒子受到的力作用,起初可以将三个方向都设置为0。之后当模拟火焰受到风的影响而偏移时,可以调整x的值。
Color over Lifetime模块
设置粒子随时间而产生的颜色变化。上面的标记控制透明度的变化,下面的标记控制颜色的变化,火焰的底部偏蓝色,从底部往上,火焰会由蓝变橙红,并且粒子生命将要结束时,将会逐渐变透明。
(4)main(主模块)的设置
Duration:发射器喷粒子的时间长度
Looping:重复持续发射粒子
Start Lifetime:单个粒子的生命周期,这里设置为0.3到0.5之间的随机值。
Start Speed:粒子的初始速度。
Start Size:粒子大小,由于火焰会忽大忽小,因此设置为0.6到1之间的随机值。
Start Rotation:粒子旋转的弧度
Gravity Modifier:粒子所受重力,由于火焰是向上窜的,因此设置为-1.
灯光闪烁效果:选中火焰,window→Animation→保存至Animation→选中Animation中的Bonfire→AddProperty→Intensity
火苗播放的很同步调整:Animation→Transform→Position
导航系统:window中nevigation →注意要将跟地形有关的物体static勾选,才能烘焙
Agent Rudius:调整可视范围
想穿过草,要将草的nevigation static关掉。然后回到nevigation重新烘焙
如果不想让人物行走在石头上面:可以选中石头。再点击一下会生成Mesh render→再回到nevigation 里Object→nevigation area→notwalkable→重新烘焙
选择人物→添加Nev Mesh Agent组件→redius、Height
给英雄添加导航组件:创建脚本hero→
if(Input.GetMouseButtonDown(0)){}
当鼠标按下左键的时候触发射线检测
{ Ray ray=Camera.main.ScreenPointToRay
(Input.mousePosition);
RaycastHit hit;
if(Physics.Raycast(ray,out hit))
{ //print(hit.point);
agent.SetDestination(nit.point);
}
}
获取射线=主相机里有ScreenPointToRay用来把屏幕坐标转化为射线,屏幕坐标获取=鼠标位置获取(Input.mousePosition);RaycastHit
hit用来保存碰撞信息;Physics.Raycast(ray,out hit);
Physics里有Raycast射线检测,Raycast里有ray射线,out hit参数;如果发生碰撞,可以检测到点击地面的哪个位置,print(hit .point);输出点的位置
要人物沿着鼠标点击的路线运动:
即Nev mesh agent沿着鼠标运动
首先引入Nev mesh命名空间Using UnityEngine.AI,然后就可以定义Nev mesh agent组件public NavMeshAgent agent,agent可以直接通过拖拽的方式赋值,
agent.SetDestination(hit.point);
有了agent 就可以通过agent里的Destination用来设置目标位置,这时候就不需要前面的print(hit.point)了
设置hero转向:在Nav Mesh Agent里设置Augular speed
控制摄像机的跟随:首先确定相机跟hero之间的偏移→用update使hero与hero保持偏移
创建相机脚本:首先定义一个Transform组件,public Transform hero,用Transform找到hero的位置,取得位置偏移
private Vector3 offset;
offset=transform.position-hero.positon;
偏移=当前位置-hero的位置
transform.position=offset+hero.positon;
相机跟主角的偏移=
控制英雄的动画播放:创建一个动画状态机,在Animation里创建Animator Controller,用来控制hero的动画播放,赋值,打开Animator,
-idle是默认状态,(控制hero的原理是通过控制其速度来控制状态),创建float参数,命名为speed,将idle与walk状态链接,箭头指向walk,设置其最大速度Greater,speed>0时,由idle切换至walk,设置其最小速度less,speed<0.1时,由walk切换至idle,
由walk切换至run时,当最大速度>2时,由run切换至walk,当最小速度<2时;这时这个动画还不太发生变化,需要给其赋值:
去代码中,获取animator 组件,public Animator anim;赋值给hero中的anim组件
anim.setfloat("speed",agent.velocity,magnitude);
状态机里 参数需要animator来设置,velocity速度,magnitude速度大小
案例4
通过案例驱动学习UGUI:
canvas中的pixcl periect:使字更柔和,如果想让字体清晰,勾选pixcl periect
图片空间:创建3D场景→保存至scene里,命名为image.字体文件命名为Text
导入图片(新建文件夹Texture),修改TextureType→Sprite(2D)→应用
应用图片:右键UI→image:
→Source Image选择需要的图片
Raycast Target:检测鼠标跟图面发不发生关系,比如图面上发生点击等事件,默认是勾选的,通过碰撞检测检测到的
等比例放大:按shift放大;setNative Size恢复原本大小
Button组件里:Hightlight Color高亮状态;
Target Graphic:修改某个图片的状态,也可以修改别的状态,只要把别的物体的Button组件赋值过来就好
Pressed Color:鼠标按下时的状态;
select color:被选中时的状态
Interactable:没办法触发点击
创建一个自己喜欢样式的Button:创建image→创建一个喜欢的样式→给一个Button组件→如果没有文字的话,可以创建子文件text
给任何一个游戏物体创建Button Manager脚本如main Camera:
添加一个方法:
public void onButtonClick()
{print("ButtonClick");}
可以添加一个带参数的方法:
public void OnButtonClick(int i)
{print("ButtonClick+"+i)}
把Button节点拖动到onClick列表的“None”那里(注意一定是节点,不能是脚本!),下拉箭头ButtonManager→OnButtonClick(int)
锚点:创建一个新场景,命名为Anchor,创建一个UI,button,一般情况下右上角的UI以右上角为锚点,左上角的UI以左上角为锚点,这样在不同屏幕里显示,UI不会被移除屏幕
在Rect Transform里修改锚点的位置
pivot:中心点
登录UI开发:
创建场景,005-Login,Canvas→UI→image
如果使图片跟屏幕分辨率保持一致,跟着画布发生变化,在Rect Transform里修改锚点的位置,按Alt选最右下角的模式,使图片与其附体保持一致→用户名、密码Text,向右对齐→创建输入框,右键InputField→修改其Content Type→Password输入密码时变为密码格式***
→Placeholder是提示信息,当真正输入时Placeholder被禁用Text是输入的信息
登录按钮设置:右键UI→Button→登录→在mineCamera 添加脚本“LoginController”→定义一个方法“public void OnloginButtonClick(){ }→找到LoginButton的OnClick,给runtime赋mineCamera的值,方法选择LogController→
OnLoginButtonClick()
输入框设置:选usernameInput选项→创建
InputField 组件,在LoginController中定义方法:先给一个命名空间using UnityEngine.UI;
public InputField usernameInput;public InputField passwordInput;→赋值→
public void OnloginButtonClick”{
string username=usernameInput.text;
string password=passwordInput.text;
if(username=="admin"&&password=="admin"){//场景跳转 sceneManager.LoadScene("001-text");
场景跳转到001-text场景
}
→选择主界面file箭头BuildSetting→把当前场景及001场景拖拽进去(这样才可以跳转成功)
(注意:在创建每个Text时记得命名
用户名:usenameLable密码:passwordLable
输入用户名:UsenameInput密码:PasswordInput登录:LoginButton)
(注意:有些名称需要引用命名空间“Using UnityEngine....”可以从左边错误提示下拉按钮找到)
密码填错时警告信息:创建一个Text→messageable(可以把整个物体禁掉,或只把Text组件禁掉)→在LoginController中添加方法“public void onLoginButtonClick()
else{messageText.text="用户名或密码错误,请重新输入”;messageText.enable=true;}
警告信息只显示一分钟:添加一个携程IEnumerator HideMessage(){yield return new WaidForSeconds(1);messageText.enable=false;}→回到else调用这个携程:StartCoroutine(HideMessage);
UI中的控件:
单选和多选按钮:
Toggle:单选按钮
男女勾选多选案例:设置两个Toggle,建立一个空物体GameObject,将两个物体放入空物体中,方便分组,在空物体中建立一个组件Toggle Group组件,将GameObject的值赋分别给男女Toggle赋值,
这时候这两个为一组,这是两个选项只有一个is on是勾选上的
Slider:控制血量、音量大小:
File就是控制进度时需要显示的部分
Image Type:是单独控制图片分割的形式的,使用其中的Solid功能时需要给图片指定一个边框:
给图片指定边框:导入图片,点击图片把Texture type更改为sprite(2D),通过Sprite Editor给图片编辑一个边框,如何下载Sprite Editor:在paceage那里右键,打开view in package Manager:unity registy是unity网络包还未导入可以下载安装,选2Dsprite;可以形成一个边框,运行时尺寸会有变化,因为image type中的slide选项,在变换图片时,不会成比例变换,上边框只会左右拉伸,左右边框只会上下拉伸。(例:一个有四角边框的图片,如果给其设置边框,再变化边框时,边框线不会发生变化)。在image type中的simple选项中放大缩小边框会被等比例拉伸的,边框线也会等比例拉伸,影响像素。
Flie Center:显示中间部分
image type中的Tild选项:平铺
(导入图片→创建一个Button→给按钮图片样式source image中导入→调节图片的边框范围)
UI中的控件:
Scrolbar:拖拽条,进度条。direction可以调节滚动条方向
Dropdown:下拉菜单
在Canvas中有panel选项,可以将控件放在同一个面板中,如果不想保留面板图片,可以勾掉image就只保留面板线框了
开发开始界面:创建新场景:009-StartScene→image→填充方式“四角填充”
声音按钮:创建UI,(导入的UI的TextureType改为Sprite2D&UI)image找到对应图片,命名为"BGM",按shift缩放到适当的大小;在此image下再创建一个image,找到相应的按钮图片SetNativeSize然后再等比例放缩,在此之下再创建一个imgae,放一个声音按钮,重复以上步骤。把以上命名为“AudioButton”,并添加一个Button组件,
添加叶子:image,shift+Alt等比例放大,命名为leaf
复制AudioButton,再做一个EmailButton
Play按钮:创建Text,调整Font Style,
Effect Distance阴影影响面积
创建shadow组建,命名为StartButton,
创建新场景,命名为010-PlayScene:
人物状态,Text:“LV50”,将此image命名为“Head”
进度条(血量值):Slider(如果不需要跟用户交互的话可以将Interactable勾选掉),在设计中往往需要的是Slider组件
创建一个image,在此之下再创建一个image用来做血量值背景“BlackBgm”,再创建一个血量值image命名为"GreenBar",添加一个Slider组件,将GreenBar添加到Fill Rect里,在GreenBar中,ImageType修改为Fill,Fill method修改为horizontal,然后就可以回到上层image中通过修改vaule来修改血量值了。Disable降低透明度变为正常状态。
给进度条加上小叶子、创建按钮+图标
设置图标,命名为“SettingButton”创建一个Button组件,复制一个做对话框图标,命名为
“DialogButton”
技能图标开发:命名为“skill”外边框,setnegativesize,在此image下面添加一个技能image,再复制一个作为这个图片的遮罩:将这图片变为黑色或者深灰色,命名为coldMask,Fill Amount可以调节。叶子、Text,给字体添加边框,即添加Outline组件,调整边框的粗细,边框的颜色。添加一个Button:
开发机能冷却效果:
添加脚本组件命名为“Skillitem":首先提供一个方法:public void OnskillClick()当技能被点击时会触发的
技能需要冷却时间的,定义一个:
public float coldTime=2;
计时器:用来计时冷却
private float timer=0;
是否处于冷却期
private bool isColding=false;
private Image coldMask;
在start中
{coldMask=transform.Find("coldMask").
GetComponent<Image>();
if (isColding){
timer+=Time.deltaTime;
coldMask.fillAmount=(coldTime-timer)/coldTime;剩余时间比例
if(timer>coldTime){isColding=false;FillAmount=0;timer=0;
}}
public void OnskillClick()
{if(isColding=false){isColding=true;timer=0;
coldMask.fillAmount=1;}
写好以上代码后,在skill的Button组件中,添加一个点击事件,OnClick→SkillitemOnSk
(注:在C#中,Tab引入系统自动给的提示命令)
按下键的时候也可以触发技能:见笔记
Panel面板:
Image→设置边框→命名为Panel→标题背景板:添加文字→字描边
面板内部边框:选择边框,调整大小→如果外边框变动,内边框也跟着变动→将内边框的锚点放在面板的四个角上,标题的锚点,设置在panel上面。
决策场景:012-Character-Knapskack
Image→重复上次Panel动作→关闭按钮“CloseButton”→导入线框→头像“Head”→人物属性:Text、Image等几个创建成一个Empty
Parent(注:全部选中子物体,让它们跟父物体的中心保持一致,这样比较好调整)
背包:Image→命名为“Knapsack"→标签的Image需要一个父image 一个子image ,标签命名为”item“→父物体上添加一个控件Toggle,复制三个,将选择变为单选:
将这三个标签再创建一个父类,命名为“itemGroup”,将三个标签先移出,调整itemGroup的位置高宽设置为100,按住ALT
拉伸一下→在itemGroup下添加组件ToggleGroup,将这三个指定给TG ,并把最后一个设置为选中状态,ison勾选,还有文字未选中情况下的遮罩状态
创建Panel1、Panel2、3
找到item1,的on vaule changed,将Panel1赋予,setactive,当选择Panel1的时候会激活,选panel的时候会禁用→设置初始状态,两个装备隐藏
物品栏:在panel3 下创建一个空物体→在其下面创建组建GridLayout Group(网格布局),命名为Grid。创建一个image,命名“item”,找一个背景,在其下方再创建一个image,找一个图标。如果直接将item拖到Grid下方,复制多了就会发现每个图标的距离很小,因此,创建一个空物体,item放在空物体下面,中心点一致。这时可以将其放在Grid下方,设置其间距
→设置分页,给每一个Panel都设置一个分页
,然后给每一个Panel做item
在UI文件里,创建一个prefabs,吧charactorPanel拖拽进去,
关卡选择:
013-LevelSelect:首先创建画布Canvas,给一个背景,再把上面的charactorPanel的预制体放入此文件夹,在charactorPanel右键prefab里有Unpack,这样就可以断开连接了,删除用不到的东西。TitleBgm,CloseButton,创建边框,做item(有上锁效果),Grid,排序方式,StartAxis,Vertical,两行两行填充。
(注意:Grid原点放在中心的时候,修改wide时向两边延伸,Grid原点放在右边,再修改wide,是从右向左延伸)
做一个锁着的状态“Levelitem-lock"放进预制体里,修改后Apply all。这样需要上锁效果的,直接拖拽预制体填充就好。
列表滚动:创建一个空物体,命名为ScrollRect,其大小跟每一页的大小是一致的如800*400,将Grid放置其下,新增组件ScrollRect,将Grid给Content、viewport赋值,∵滚动是受超出范围来,只有有图片的时候才能检测到滚动,∴在ScrollRect里添加一个image,image里有一个Raycast Padding是可以检测的。如果垂直滑动跟水平滑动都可以的话,把Scroll里的Vertical关闭,把超出界限的部分隐藏,创建一个Mask,要将之前image的颜色透明度调回正常,之前是透明,将show Mask Graphic取消掉
分页滚动:在ScrollRect里添加脚本“LevelScrollRectangle”,脚本思路见笔记
(注意:以上内容都做完但是还是滚动不了的原因,出现在刚开始的步骤,Grid的宽度设置600*350,这是一个页面的宽度,需要4个页面,2400*350,要注意Grid的中心点调至左边,调中心点还有看工具栏的选项是中心点还是轴心点,选中心点然后才能移动中心点的位置,后面移动不了,都是因为这个步骤错了)
按页滚动:创建空物体“PageButton”→在其下创建image“圆点”再其下创建image“叶子”→在image添加一个Toggle,给其赋值,这样勾选ison,可以使叶子显示或隐藏,Ctrl+D,复制,这样四个圆点就做好了,在PageButton设置ToggleGroup,赋值,这样点击圆点,叶子就能显示了,回到脚本监听OnvauleChange方法,见笔记
任务栏:创建场景014-Taxtlist→将ChatacterPanel→先取消连接,然后删除不用的内容,可以按住Alt调整画布的宽度,创建任务条,给其边框使其拖拽不变形,创建“完成”按钮,给这个Text一个outline,给这个按钮添加一个Button,命名为DownButton,将以上内容放在一个文件下面,命名为“item”
任务列表布局:创建一个空物体“Verticallist”,在其身上创建一个VerticalLayoutGroup,将item做成预制体,然后放入垂直列表内,然后可以复制多份,然后设置其滚动区域image、Mask、然后上下滑动(取消horizontal勾选)设置面板,
声音大小滑动器:新场景015-Settings,Text声音→slider→设置slider背景、音量条、拖动按钮样式, 开关样式:创建image做打开模式下的开关“on",再创建关闭样式“off",添加组件“Toggle”,由于Toggle只能显示图片的开关,不能连接到游戏上,所以创建代码:"Mytoggle",代码逻辑见笔记
登陆面板:016-Login:按住ALT键对称缩放,用户名、密码,对于密码,content type要改为password。
坦克大战:
1.场景搭建:main Camera:设置Camera的大小为8.5,颜色调为黑色,注:信息显示面板Console,在window里打开,可以看报错信息,
切割素材:用sprite editor→Grid by Cell Size(以固定大小来切割),调整到合适的尺寸,切好图集→保存场景→创建文件夹Scence
创建玩家,玩家比对着Cube更改尺寸,创建一个文件夹,Prefabs,将玩家创建为预制体。再做墙,障碍向右拖拽Barrier,再做Grass,再做一个Heart(老窝),动画命名为“Bom”,将以上的预制体全部拖到预制体文件夹里,在预制体文件夹里创建一个Effect文件夹,存放特效。把爆炸特效的控制器放在一个文件夹里
玩家出生时会有一个屏障效果:shield,
玩家游戏时动作转换:创建一个脚本:见笔记,创建数组后,将需要用的图片赋予public sprite
碰撞检测:创建2D碰撞器,(在预制体上添加碰撞器是无法添加到同样的克隆体上的,因此)
给player添加一个刚体组件,(注:是rigibody2D),运行起来会发现player很快运动,这时将Gravity Scale重力,调整为0,给map里的其他物体添加碰撞器,草坪不需要交互,所以取消Grass的碰撞器
player运动时图片方向斜着,解决方法:在
rigidbody→constrains→Freeze Rotation Z
player在碰撞到物体时会有点鬼畜,解决办法:用代码:生命周期函数,见笔记
控制player的运动方向:脚本笔记
让特效覆盖在玩家的上面:精灵渲染器Sprite Renderer里,有sorting layer,order layer,sorting layer是层级,order in layer层级顺序。如,将order in layer设置为1,层级越大越后渲染,也就是说,最不想让谁被覆盖掉,就把谁设置为大,这样可以最后被渲染。
将子弹拖入场景,拖入坦克文件夹,order in Layer,设置为1
写玩家的攻击方法:写脚本 →将子弹的预制体赋给Tank里的Bullect Prefab,然后在脚本里调用一下方法
子弹旋转角度:见脚本
攻击CD的加入,触发器与碰撞器:在子弹预制体身上加一个脚本,“Bullect”,在脚本中控制方向
触发检测:给子弹添加一个触发器,(因为子弹不需要碰撞效果,所以只要一个触发器)BoxCollider2D,两方都有碰撞器组件,一方的is Trigger勾选上的,最好碰撞的那方有刚体,即在Bullet里加上Rigidbody2D。在脚本里给子弹加上触发检测的方法→给物体添加标签,add Tag,然后在脚本里编写触发检测的语句。→→做个空气墙:在界面复制一个墙体,把其中的渲染器删掉,即把sprite Renderer删掉,命名为“Air Barrier”,然后把它拖入Map文件夹做预制体
玩家无敌方法与死亡方法:见脚本。
死亡方法:坦克在break之前需要爆炸特效及生命力减1等效果。需要用到爆炸特效→产生爆炸特效:给爆炸特效一个脚本:“Explosion”,然后在player调用一下Explosion脚本至explosion Prefab.
无敌方法:被保护状态,如果玩家处于被保护状态,让玩家不会销毁。见脚本。然后,由于不能一直让特效产生,所以,找到玩家,把“shield”放在玩家下方然后reset一下,这样当玩家处于无敌状态时显示一下,之后不是无敌状态时就关闭。见脚本修改。
判断玩家子弹还是敌人子弹:见脚本
注意:写完脚本,记得修改frefabs上的标签,改成各自的名称。
如果子弹射击没有反应:有可能是Order in Layer的渲染层级跟被碰撞物体的渲染层级不在一个层级,所以要想使两个物体发生作用,要将其渲染层级调至一起。
区分玩家子弹与敌人子弹:将玩家子弹重命名,为playerBullect,并勾选 is player Bullect,然后再复制一个playerBullect,命名为EnemyBullect,勾选掉is player Bullect.
敌人制作:复制玩家,然后把无敌状态删除。更换图标,删除玩家脚本,重新添加新的脚本。
将玩家脚本复制到敌人脚本里:见脚本
老窝的爆炸效果:找到heart脚本,
爆炸重生脚本:Bron脚本,private woid BornTank()→调用一个延时特效Invoke("BornTank",0.8f)→引用一下玩家→延时销毁
设置第二个玩家:SmallEnemy→把图片的切换添加一下,精灵数组里添加→敌人不需要保护状态,把Explosion跟Bullet添加好就好。smallEnemy的移动速度改为4,打开Born脚本:见笔记。记得把enemy挂载的脚本改为enemy的脚本。
初始化地图工具: 1.测试场景大小:选中一个敌人,拖动敌人拖到左下角的位置,例坐标为-10,-8,0,拖到中间位置为0,-8,0,所以地图的大小大约是长20,宽18。所以创建一个GameObject→命名为MapCreation→新添加脚本“MapCreation”,见脚本。→赋值后只留一个小坦克来测试。→实例化老家,在(0,-8,0)的位置来实例化→见脚本→墙中间有缝隙,可能是墙有点小,可以缩放为3.2
游戏运行起来后,在界面会有罗列,我们想让罗列的内容在一个物体下,如MapCreation,面板看起来不会很混乱,因此添加一个方法→在MapCreation脚本里,见脚本→让它随机产生敌人,而且不在一个地方产生两个物体,见脚本。
实例化地图:见脚本。把草的渲染参数调为1。
玩家管理:设置一个GameObject→然后更名为“PlayerManager”→增加一个脚本
UI设计:给main Camera设置为灰色,拖黑色背景,放大至跟原先屏幕即5:4的大小差不多,然后把main Camera调整为16:10→BackGround的渲染层级设为-2
Img-PlayerScore:找到相应的图片,调整至居右对其,设置Text,字写20,字体颜色为白色,
在PlayerManager的脚本里设置一下,见脚本
- 游戏结束UI:创建一个UI,找到相应图片,然后去脚本修改。