找回密码
 立即注册
首页 业界区 科技 从开始到贪吃蛇

从开始到贪吃蛇

尤晓兰 昨天 19:36
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)
您需要登录后才可以回帖 登录 | 立即注册