Day 2025.1.21
unity方法
关于transform组件的使用
直接使用transform组件
transform.Translate()
用于当前脚本挂载组件的移动
player = this.gameObject;
用于挂载当前实体对象
Day 2025.1.23
关于c#面向对象
Public ObjState{
Move,
Stop,
Lockmove
}
表示ObjState只有3个状态
If(ObjState == move){
Num++;
}
C# class类的学习
Day 2025.1.24
Static 一般的变量要在实例化类后才能访问,加了static后不实例化也可以访问
Day 2025/1/24
Materials 材质包
关于unity的生命周期
Void Start(){} 在游戏开始时运行
Void update(){} 每一帧重复执行的函数,一般来说一个游戏每秒60帧
关于unity的控制台
用debug.log(“”)输出
Vector3
是unity中的一种向量类,用于表示位置,方向和运动等概念
// 给rd施加一个向右的力,默认为1牛的力
rd.AddForce(Vector3.right);
// 施加2牛的力
rd.AddForce(new Vector3(2,0,0));
Input.getAxis(“Horizontal”) 获取当前键盘键入字符,水平
Input.getAxis(“Vertical”) 获取当前键盘键入字符,垂直
碰撞发生的三个事件:碰撞、碰撞中、碰撞后
private void OnCollisionEnter(Collision collision) {
Debug.Log("碰撞检测.");
}
private void OnCollisionExit(Collision collision) {
Debug.Log("碰撞检测.");
}
private void OnCollisionStay(Collision collision) {
Debug.Log("碰撞检测.");
}
Day 2025/1/28
今天学习游戏碰撞检测
当前模型碰撞检测:
Private void OnCollisionEnter(Collision collisio){
If(collisio.gameObject.tag == “food”){
}
}
Destory(collision.gameObject) 摧毁模块
触发检测:跟碰撞检测差不多,区别是触发检测没有实物碰撞
private void OnTriggerEnter(Collider other) {
if (other.gameObject.tag == "food")
{
Destroy(other.gameObject);
}
}
触发检测
碰到物体后销毁及增加分数
引入命名空间
using UnityEngine.UI;
获取分数组件
定义分数变量
Int score = 0
Public Text scoreText;
更新分数
Score++
scoreText.text = XXXXX
游戏胜利后显示胜利文本
winText.SetActive(true);
完成
Day 2025/1/29
Time.deltatime 每一帧之间执行的时间
1/deltatime 则是每秒执行的帧数
void Update()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
transform.Translate(new Vector3(h,v,0) * speed * Time.deltaTime);
}
使用算法实现模块每秒执行速度
也可以用生命周期FixedUpdate
private void FixedUpdate() {
}
修正执行速度,大多数用算法
通过预制体+脚本新建组件(子弹)
public GameObject bulletPrefab;
void Start()
{
GameObject.Instantiate(bulletPrefab,transform.position,transform.rotation);
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
GameObject.Instantiate(bulletPrefab,transform.position,transform.rotation);
}
}
检测鼠标是否按下后创建子弹
void Update()
{
if (Input.GetMouseButtonDown(0))
{
GameObject bullet = GameObject.Instantiate(bulletPrefab,transform.position,transform.rotation);
Rigidbody rd = bullet.GetComponent();
// rd.AddForce(Vector3.forward*100);
rd.velocity = Vector3.forward*30;
}
}
获取刚体组件并且施加前进的力
Rd.velocity = vector3.forward
Day 2025/1/30
学习GUI
今日主要重点:查找组件find方法
Day 2025/2/1
关卡选择的制作:
设置背包面板为预制体,实例化预制体,然后与预制体断开链接,删除背包内元素
设置超宽的关卡选择,然后使用scroll组件再使用mask组件进行滑动管理
实现关卡选择页功能
- 使用scroll rect自带的value chanhed事件
- 使用拖拽接口
public class levelScroll : MonoBehaviour,IBeginDragHandler,IEndDragHandler
{
public void OnBeginDrag(PointerEventData eventData)
{
throw new System.NotImplementedException();
}
public void OnEndDrag(PointerEventData eventData)
{
throw new System.NotImplementedException();
}
}
- 获取scroll组件scroll = getcomponet
- 定义一个float数组,当scroll.horizontalnormalizedposition == 1的4分之一的相近值则跳到四分之一
- 使用线性函数math.lerp实现页面切换功能
public void OnEndDrag(PointerEventData eventData)
{
float currentPosition = scroll.horizontalNormalizedPosition;
if (currentPosition0.25 && currentPosition0.75)
{
index = 2;
}
// 指定页
// scroll.horizontalNormalizedPosition = pagePosition[index];
isMoving = true;
}
- 原视频用了比较复杂的算法,这边用的是自己觉得比较简单的方法
void Update()
{
// 如果正在移动,则使用线性插值函数移动
// 线性函数用法:Mathf.Lerp(起始值,目标值,速度)
if (isMoving)
{
scroll.horizontalNormalizedPosition = Mathf.Lerp(scroll.horizontalNormalizedPosition,pagePosition[index],Time.deltaTime*speed);
if (Math.Abs(scroll.horizontalNormalizedPosition-pagePosition[index])=0.4f)
{
Shoot();
timeVal = 0;
}else{
timeVal+=Time.deltaTime;
}
}
void Update()
{
transform.Translate(transform.up*bulletSpeed*Time.deltaTime,Space.World);
}
给子弹添加触发器boxcolider和刚体rigidbody -完成
物体添加tag --完成
射击检测和空气墙 --完成
编写玩家被击中-销毁状态
private void Die(){
if (isDefend)
{
return;
}
// 生成爆炸特效
Instantiate(deathAnimation,transform.position,transform.rotation);
// 摧毁组件
Destroy(gameObject);
}
在子弹脚本中调用死亡函数
private void OnTriggerEnter2D(Collider2D collision) {
switch (collision.tag)
{
case "wall":
break;
case "enemy":
break;
case "obst":
break;
case "airObst":
break;
case "tank":
// 使用玩家组件下的die方法
collision.SendMessage("Die");
break;
}
Destroy(gameObject);
}
在子弹脚本中定义是否为玩家子弹的变量
If(!isTankBullet)collision.SendMessage("Die")
编写heart被摧毁脚本
Destory(collision.gameobject)
Destory(gameobject)
除了子弹,其他组件不需要勾选is trigger
今天就纠结这个istrigger了,学了个锤子
Day 2025/2/6
喝了酒,犯困,什么都没学
Day 2025/2/6
敌人的制作,家爆炸特效以及出生特效
前两个没什么好说的,敌人的脚本跟玩家的差不多
家爆炸特效是在heart变更特效图后生成爆炸特效
延时出生和延时销毁出生特效
void Start()
{
// 延时生成和延时销毁
Invoke("Generate",0.7f);
Destroy(gameObject,0.7f);
}
private void Generate(){
Instantiate(tankPrefab,transform.position,Quaternion.identity);
}
1. 新建一个玩家子弹模板,敌人子弹模板,玩家模板,敌人1模板,敌人2模板
2. 在出生特效模板中定义一个玩家模板,一个敌人数组,
if createPlayer则生成玩家,else生成随机类型敌人
3. 编写敌人AI,每隔3秒射击子弹,每4秒移动一次需要用到随机函数
int num = Random.Range(0,8) //不包括8
修bug:包括敌人tag,子弹tag,子弹脚本-击中敌人
编写地图生成脚本
新建一个空组件createMap
先生成家
注意:awake函数执行在start函数之前,所以生成地图使用awake函数
组件生成后设置父组件
GameObject itemGo = Instantiate(obj,position,rotation);
itemGo.transform.SetParent(gameObject.transform);
编写地图产生随机障碍物和空气墙
定义一个已有位置数组
一般来说,墙生成60个其他物体生成20个
生成玩家和敌人
生成born特效,设isPlayer为true
最开始顶上3个位置生成3个敌人
然后每隔5秒生成1个敌人
InvokeRepeating("createEnemy",4,5);
修复bug:敌人碰到会推着走
设置敌人碰撞检测:让敌人碰到后跳过移动间隔,设置一开始敌人向下走,减少碰撞
玩家状态管理
敌人脚本-死亡得分
玩家脚本-死亡就调用 状态管理death = true
把玩家状态创建为一个全局单例--即不用引入到其他脚本中就可以使用
private static status instance;
public static status Instance
{
get
{
return instance;
}
set
{
instance = value;
}
}
private void Awake() {
instance = this;
}
//固定写法
状态管理中玩家有3条血,死亡一次--
Day2025/2/7
修复:家被击毁,禁止玩家发射和移动行为
Heart--die--status--isDefeat = true
Player--fixedupdate--status.isdefeat
游戏背景的制作,玩家得分和生命显示,游戏失败显示
要在UI里面新建组件
首页制作和音效
有首页的光标选择
w切换光标位置1,s切换光标位置2
Flag为1时切换scene1
然后就是切换场景sceneManager
返回主页
视频里用的是3秒后自动返回主界面,我们可以设置空格键返回
Heart引入音效组件
public AudioClip dieAudio;
直接播放音效
AudioSource.PlayClipAtPoint(dieAudio,transform.position);
坦克死亡:直接在爆炸特效上添加一个音频组件,生命周期开始时只播放一次
打到障碍物:在子弹脚本上调用障碍物的播放音效方法
Day 2025/2/8
制作子弹音效
直接在子弹上添加音效组件
玩家移动音效
当一个组件上有多个音效:先在脚本内定义音效数组,然后添加音效组件,控制组件的播放切换
if (Math.Abs(h) |