Unity|小游戏复刻|见缝插针3代码(C#)

![[Pasted image 20250125225057.png]]

思路

游戏整体思路
这是一个简单的游戏,玩家通过点击鼠标让钉子(Pin)飞向目标(Circle)。如果钉子的头部(PinHead)与目标发生碰撞,则游戏结束。游戏结束时,会有一个动画效果,然后重新加载当前场景。

代码思路
1. 游戏管理器(GameManager.cs

  • 功能:作为游戏的核心管理器,负责游戏的整体逻辑,包括钉子的生成、计分、游戏结束处理等。
  • 关键逻辑
    • 初始化:在 Start() 方法中,查找起始位置和生成位置,获取主相机引用,并生成第一个钉子。
    • 玩家操作:在 Update() 方法中,检测鼠标点击事件。每次点击时,增加得分,让当前钉子开始飞行,并生成新的钉子。
    • 游戏结束:当钉子头部与目标碰撞时,调用 GameOver() 方法。停止目标的旋转,并启动游戏结束动画。
    • 游戏结束动画:通过 GameOverAnimation() 协程,逐渐改变相机的背景颜色和正交大小,完成后重新加载当前场景。
      2. 钉子控制(Pin.cs
  • 功能:控制钉子的行为,包括移动到起始位置、飞行到目标位置等。
  • 关键逻辑
    • 初始化:在 Start() 方法中,设置钉子的起始位置和目标位置。
    • 移动逻辑:在 Update() 方法中,根据 isFlyisReach 的状态,控制钉子的移动。
      • 如果 isFlyfalse,钉子移动到起始位置。
      • 如果 isFlytrue,钉子移动到目标位置。
    • 开始飞行:通过 StartFly() 方法,让钉子开始飞行。
      3. 钉子头部碰撞检测(PinHead.cs
  • 功能:检测钉子头部是否与目标发生碰撞,触发游戏结束。
  • 关键逻辑
    • 碰撞检测:在 OnTriggerEnter2D() 方法中,检测带有 “PinHead” 标签的碰撞。如果检测到碰撞,调用 GameManagerGameOver() 方法。
      4. 自旋转组件(RotateSelf.cs
  • 功能:控制目标(Circle)的自旋转行为。
  • 关键逻辑
    • 旋转逻辑:在 Update() 方法中,每帧更新时,绕 Z 轴旋转目标对象。

代码协同工作

  1. 游戏开始
    • GameManagerStart() 方法中初始化游戏,生成第一个钉子。
    • PinStart() 方法中初始化钉子的位置和目标位置。
  2. 玩家操作
    • 玩家点击鼠标左键时,GameManagerUpdate() 方法检测到点击事件。
    • 增加得分,调用当前钉子的 StartFly() 方法,让钉子开始飞行。
    • GameManager 生成新的钉子。
  3. 钉子飞行
    • PinUpdate() 方法控制钉子的移动。
    • 如果钉子头部与目标发生碰撞,PinHeadOnTriggerEnter2D() 方法检测到碰撞,调用 GameManagerGameOver() 方法。
  4. 游戏结束
    • GameManagerGameOver() 方法停止目标的旋转,并启动游戏结束动画。
    • GameOverAnimation() 协程逐渐改变相机的背景颜色和正交大小。
    • 动画完成后,重新加载当前场景,游戏重新开始。

总结

  • GameManager:作为游戏的核心管理器,负责整体逻辑。
  • Pin:控制钉子的移动和飞行行为。
  • PinHead:检测钉子头部与目标的碰撞,触发游戏结束。
  • RotateSelf:实现目标的自旋转效果。
    通过这些脚本的协同工作,游戏实现了玩家操作、得分、碰撞检测和游戏结束等核心功能。

代码

GameManager
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using TMPro;
using System.Collections;

public class GameManager : MonoBehaviour
{
    // 变量定义
    private Transform startPosition; // 钉子的起始位置
    private Transform spawnPosition; // 钉子的生成位置
    private Pin currentPin; // 当前活动的钉子
    private bool isGameOver = false; // 标记游戏是否结束
    private int score = 0; // 玩家的得分
    private Camera mainCamera; // 主相机的引用

    public TextMeshProUGUI scoreText; // 显示得分的 UI 文本
    public GameObject pinPrefab; // 钉子的预制体
    public float speed = 3; // 动画过渡的速度

    // Start 是在 MonoBehaviour 创建后首次调用
    void Start()
    {
        // 查找场景中的起始位置和生成位置
        startPosition = GameObject.Find("StartPosition").transform;
        spawnPosition = GameObject.Find("SpawnPosition").transform;
        // 获取主相机的引用
        mainCamera = Camera.main;
        // 生成第一个钉子
        SpawnPin();
    }

    // Update 每帧调用一次
    void Update()
    {
        // 如果游戏已经结束,直接返回
        if (isGameOver) return;
        // 检测鼠标左键点击
        if (Input.GetMouseButtonDown(0))
        {
            // 增加得分
            score++;
            // 更新得分显示
            scoreText.text = score.ToString();
            // 让当前钉子开始飞行
            currentPin.StartFly();
            // 生成新的钉子
            SpawnPin();
        }
    }

    // 生成钉子的方法
    void SpawnPin()
    {
        // 实例化钉子预制体
        currentPin = GameObject.Instantiate(pinPrefab, spawnPosition.position, pinPrefab.transform.rotation).GetComponent<Pin>();
    }

    // 游戏结束的方法
    public void GameOver()
    {
        // 如果游戏已经结束,直接返回
        if (isGameOver) return;

        // 停止 "Circle" 对象的旋转
        GameObject.Find("Circle").GetComponent<RotateSelf>().enabled = false;
        // 启动游戏结束动画
        StartCoroutine(GameOverAnimation());
        // 标记游戏结束
        isGameOver = true;
    }

    // 游戏结束动画的协程
    IEnumerator GameOverAnimation()
    {
        // 逐渐改变相机的背景颜色和正交大小
        while (true)
        {
            mainCamera.backgroundColor = Color.Lerp(mainCamera.backgroundColor, Color.red, speed * Time.deltaTime);
            mainCamera.orthographicSize = Mathf.Lerp(mainCamera.orthographicSize, 4, speed * Time.deltaTime);
            // 检查正交大小是否接近目标值
            if (Mathf.Abs(mainCamera.orthographicSize - 4) < 0.01f)
            {
                break;
            }
            // 暂停协程直到下一帧
            yield return null;
        }
        // 等待 0.2 秒
        yield return new WaitForSeconds(0.2f);
        // 重新加载当前场景
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
    }
}
Pin
using UnityEngine;

public class Pin : MonoBehaviour
{
    public float speed = 5; // 钉子的移动速度
    private bool isFly = false; // 标记钉子是否正在飞行
    private bool isReach = false; // 标记钉子是否已到达起始位置
    private Transform startPosition; // 钉子的起始位置
    private Vector3 targetCirclePos; // 钉子的目标位置
    private Transform circle; // 目标圆圈的引用

    // Start 是在 MonoBehaviour 创建后首次调用
    void Start()
    {
        // 查找起始位置和目标圆圈
        startPosition = GameObject.Find("StartPosition").transform;
        circle = GameObject.Find("Circle").transform;
        // 设置目标位置
        targetCirclePos = circle.position;
        targetCirclePos.y -= 1.54f;
    }

    // Update 每帧调用一次
    void Update()
    {
        // 如果钉子没有开始飞行
        if (isFly == false)
        {
            // 如果钉子没有到达起始位置
            if (isReach == false)
            {
                // 移动钉子到起始位置
                transform.position = Vector3.MoveTowards(transform.position, startPosition.position, speed * Time.deltaTime);
                // 检查是否到达起始位置
                if (Vector3.Distance(transform.position, startPosition.position) < 0.05f)
                {
                    isReach = true;
                }
            }
        }
        else
        {
            // 移动钉子到目标位置
            transform.position = Vector3.MoveTowards(transform.position, targetCirclePos, speed * Time.deltaTime);
            // 检查是否到达目标位置
            if (Vector3.Distance(transform.position, targetCirclePos) < 0.05f)
            {
                // 将钉子附加到目标圆圈上
                transform.position = targetCirclePos;
                transform.parent = circle;
                // 标记钉子停止飞行
                isFly = false;
            }
        }
    }

    // 开始飞行的方法
    public void StartFly()
    {
        isFly = true;
        isReach = true;
    }
}
PinHead
using UnityEngine;

public class PinHead : MonoBehaviour
{
    // 当触发器检测到碰撞时调用
    private void OnTriggerEnter2D(Collider2D collision)
    {
        // 如果碰撞对象的标签是 "PinHead"
        if (collision.CompareTag("PinHead"))
        {
            // 调用 GameManager 的 GameOver 方法
            GameObject.Find("GameManager").GetComponent<GameManager>().GameOver();
        }
    }
}
RotateSelf
using UnityEngine;

public class RotateSelf : MonoBehaviour
{
    public float speed = 90; // 旋转速度

    // Start 是在 MonoBehaviour 创建后首次调用
    void Start()
    {
        // 无初始化逻辑
    }

    // Update 每帧调用一次
    void Update()
    {
        // 绕 Z 轴旋转对象
        transform.Rotate(new Vector3(0, 0, -speed * Time.deltaTime));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值