入门级案例学习 - 见缝插针
创建工程和场景
导入素材,没啥好说的
开发旋转的小球和分数显示
创建旋转的小球
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oLPnaxZo-1680961538151)(C:\Users\CoreDawg\AppData\Roaming\Typora\typora-user-images\image-20230408191257026.png)]‘
简单设置一下transform和颜色大小啥的,没啥技术含量
加一个GUI的text显示分数
EventSystem先删除掉
reset居中,字体左右上下居中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oA51wFSZ-1680961538152)(C:\Users\CoreDawg\AppData\Roaming\Typora\typora-user-images\image-20230408191842766.png)]
canvas的渲染模式改为World Space
因为这个模式方便缩小到游戏开发环境一样的大小
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qJC1T6Ie-1680961538153)(C:\Users\CoreDawg\AppData\Roaming\Typora\typora-user-images\image-20230408192140702.png)]
借助scale进行整体的缩小[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jDZB1Qxu-1680961538153)(C:\Users\CoreDawg\AppData\Roaming\Typora\typora-user-images\image-20230408193558999.png)]
事件摄像机设置成MainCamera
控制小球旋转
直接利用transform的Rotate属性控制旋转
//声明一个旋转速度
public float speed=90;//度数
void Update()
{
//通过Rotate方法控制旋转
//只围绕Z轴旋转,xy都为0
transform.Rotate(new Vector3(0, 0,speed * Time.deltaTime));
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iXdFt9QW-1680961538153)(C:\Users\CoreDawg\AppData\Roaming\Typora\typora-user-images\image-20230408194914975.png)]
在scene模式下能观察到旋转效果
在speed前面加上一个 - 就能改变旋转的方向
开发针的Prefab预制体
给针头添加碰撞器
针的发射
思路:实例化的屏幕外边,运动进来
创建两个空物体控制位置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hsq4l8NH-1680961538154)(C:\Users\CoreDawg\AppData\Roaming\Typora\typora-user-images\image-20230408195739243.png)]
这样能方便定位
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-svB3CqGY-1680961538154)(C:\Users\CoreDawg\AppData\Roaming\Typora\typora-user-images\image-20230408195846597.png)]
吧针放在StartPoint下面,把针设置成000
创建空物体GameManager 用于管理针的实例化
创建对应脚本
通过Find方法拿到点的transform组件
注意字符串要和需要的组件写的一致
//先拿到两个点
private Transform startPoint;
private Transform spawnPoint;
void Start()
{
//通过GameObject拿到
startPoint = GameObject.Find("StartPoint").transform;
spawnPoint = GameObject.Find("SpawnPoint").transform;
}
实例化针
先拿到针的预制体
public GameObject pinPrefab;//注意public属性需要拖拽赋值
生成针的方法
void Start()
{
//通过GameObject拿到
startPoint = GameObject.Find("StartPoint").transform;
spawnPoint = GameObject.Find("SpawnPoint").transform;
//调用实例化方法
SpawnPin();
}
//实例化 针
void SpawnPin()
{
GameObject.Instantiate(pinPrefab, spawnPoint.position, pinPrefab.transform.rotation);
}
控制针移动到就位位置
Movetowards方法
当前位置,目标位置,距离
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Pin : MonoBehaviour
{
//真运动的速度
public float speed=5;
//因为针有两段运动,所以先声明两个布尔值
private bool isFly = false;
private bool isReach = false;
//拿到位置
private Transform startPoint;
void Start()
{
startPoint = GameObject.Find("StartPoint").transform;
}
void Update()
{
if (isFly == false)//还没开始向圆球移动
{
if (isReach == false)//没到达开始点
{
//把移动得到的新的位置给到针
transform.position= Vector3.MoveTowards(transform.position, startPoint.position, speed * Time.deltaTime);
}
}
}
}
判断是否达到目标位置
if (Vector3.Distance(transform.position, startPoint.position) < 0.05f)
{
isReach =true;//等于true之后就不会再重复执行这段代码了,节约性能
}
}
控制针的插入
鼠标输入控制发射
//Update方法检测鼠标输入
void Update()
{
if (Input.GetMouseButtonDown(0))
{
}
}
给针加一个飞行方法
首先对针的实例化进行补充
//持有一个当前针的引用
private Pin currentPin;
//实例化 针
void SpawnPin()
{
currentPin = GameObject.Instantiate(pinPrefab, spawnPoint.position, pinPrefab.transform.rotation).GetComponent<Pin>();
}
完善鼠标方法调用
//Update方法检测鼠标输入
void Update()
{
if (Input.GetMouseButtonDown(0))
{
currentPin.StartFly();
}
}
确定飞行方法的基础条件
public void StartFly()
{
isFly = true;
isReach = true;
}
用Find方法拿到圆的位置
private Transform circle;
void Start()
{
circle = GameObject.Find("Circle").transform;
}
运动
else
{
transform.position = Vector3.MoveTowards(transform.position, circle.position, speed * Time.deltaTime);
//判断是否到达目标位置
//注意不能到达圆圈的中心,而是到达圆圈的边缘就好
}
控制针达到的位置和针的连环发射
控制距离
计算针头和圆圈的差距
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QQJbQrqn-1680961538154)(C:\Users\CoreDawg\AppData\Roaming\Typora\typora-user-images\image-20230408205045583.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6NKl5Sc9-1680961538155)(C:\Users\CoreDawg\AppData\Roaming\Typora\typora-user-images\image-20230408205054684.png)]
1.7-0.18=1.52
//声明目标位置
private Vector3 targetCirclePos;
targetCirclePos = circle.position;
targetCirclePos.y -= 1.52f;
修改移动
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;//结束执行
}
实例化下一个针
//Update方法检测鼠标输入
void Update()
{
if (Input.GetMouseButtonDown(0))
{
currentPin.StartFly();
SpawnPin();//重新实例化一个新的针
}
}
针头的碰撞和游戏结束的处理
通过针头的碰撞判定游戏失败
先给针头加刚体组件
然后在碰撞里面勾选trigger
重力设置为0
给针头上tag
游戏失败的方法:
//游戏失败的方法
public void GameOver()
{
}
在针头的判断里调用失败方法
//触发器
private void OnTriggerEnter2D(Collider2D collision)
{
//先判断另一个碰撞体是不是也是针头
if (collision.tag == "PinHead")
{
//先查找GameManager
GameObject.Find("GameManager").GetComponent<GameManager>().GameOver();
}
}
但是这个会多次触发,怎么控制只处理一次呢,定义一个布尔变量
private bool isGameOver=false;//是否游戏失败
//游戏失败的方法
public void GameOver()
{
if (isGameOver) return;
//禁用掉小球的旋转
GameObject.Find("Circle").GetComponent<RotateSelf>().enabled = false;
isGameOver = true;
}
补充游戏失败的方法
控制分数的显示
定义一个变量存储当前分数
private int score = 0;
持有一个Text组件
//持有一个Text组件
public Text scoreText;
每次按下鼠标分数增加
void Update()
{
if (isGameOver) return;
if (Input.GetMouseButtonDown(0))
{
score++;
scoreText.text = score.ToString();
currentPin.StartFly();
SpawnPin();//重新实例化一个新的针
}
}
游戏结束的动画思路
颜色梗概 - 通过camera的背景颜色渐变
失败之后修改size - 整体画面变大
游戏重启
游戏结束动画的显示(课程结束)
通过camera组件实现动画控制
//拿到camera组件
private Camera maincamera;
赋值
void Start()
{
maincamera = Camera.main;
}
用协程控制动画
定义动画速度
//定义一个动画速度方法
public float speed = 3;
协程
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 0;//每次循环暂停一帧
}
//让动画暂停一下
yield return new WaitForSeconds(1);
}
Lerp方法:插值运算,由当前渐变到目标
重新加载场景
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
//游戏失败的方法
public void GameOver()
{
if (isGameOver) return;
//禁用掉小球的旋转
GameObject.Find("Circle").GetComponent<RotateSelf>().enabled = false;
StartCoroutine(GameOverAnimation());
isGameOver = true;
}
调用动画
所有脚步
针头
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PinHead : MonoBehaviour
{
//触发器
private void OnTriggerEnter2D(Collider2D collision)
{
//先判断另一个碰撞体是不是也是针头
if (collision.tag == "PinHead")
{
//先查找GameManager
GameObject.Find("GameManager").GetComponent<GameManager>().GameOver();
}
}
}
针
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Pin : MonoBehaviour
{
//真运动的速度
public float speed=5;
//因为针有两段运动,所以先声明两个布尔值
private bool isFly = false;
private bool isReach = false;
//拿到点位置
private Transform startPoint;
//拿到圆的位置
public Transform circle;
//声明目标位置
private Vector3 targetCirclePos;
void Start()
{
startPoint = GameObject.Find("StartPoint").transform;
//通过标签查找circle
//circle = GameObject.FindGameObjectsWithTag("Circle").transform;
circle = GameObject.Find("Circle").transform;
targetCirclePos = circle.position;
targetCirclePos.y -= 1.52f;
}
void Update()
{
if (isFly == false)//还没开始向圆球移动
{
if (isReach == false)//没到达开始点
{
//把移动得到的新的位置给到针
transform.position= Vector3.MoveTowards(transform.position, startPoint.position, speed * Time.deltaTime);
if (Vector3.Distance(transform.position, startPoint.position) < 0.05f)
{
isReach =true;//等于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;
}
}
管理器
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
//先拿到两个点
private Transform startPoint;
private Transform spawnPoint;
//持有一个当前针的引用
private Pin currentPin;
public GameObject pinPrefab;//注意public属性需要拖拽赋值
private bool isGameOver = false;//是否游戏失败
private int score = 0;
//持有一个Text组件
public Text scoreText;
//拿到camera组件
private Camera maincamera;
//定义一个动画速度方法
public float speed = 3;
void Start()
{
//通过GameObject拿到
startPoint = GameObject.Find("StartPoint").transform;
spawnPoint = GameObject.Find("SpawnPoint").transform;
maincamera = Camera.main;
//调用实例化方法
SpawnPin();
}
//实例化 针
void SpawnPin()
{
currentPin = GameObject.Instantiate(pinPrefab, spawnPoint.position, pinPrefab.transform.rotation).GetComponent<Pin>();
}
//游戏失败的方法
public void GameOver()
{
if (isGameOver) return;
//禁用掉小球的旋转
GameObject.Find("Circle").GetComponent<RotateSelf>().enabled = false;
StartCoroutine(GameOverAnimation());
isGameOver = true;
}
//Update方法检测鼠标输入
void Update()
{
if (isGameOver) return;
if (Input.GetMouseButtonDown(0))
{
score++;
scoreText.text = score.ToString();
currentPin.StartFly();
SpawnPin();//重新实例化一个新的针
}
}
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 0;//每次循环暂停一帧
}
//让动画暂停一下
yield return new WaitForSeconds(0.3f);
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
旋转
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotateSelf : MonoBehaviour
{
//声明一个旋转速度
public float speed=90;//度数
void Update()
{
//通过Rotate方法控制旋转
//只围绕Z轴旋转,xy都为0
transform.Rotate(new Vector3(0, 0,speed * Time.deltaTime));
}
}
判断到达目标值循环结束
if (Mathf.Abs(maincamera.orthographicSize - 4) < 0.01f)
{
break;
}
yield return 0;//每次循环暂停一帧
}
//让动画暂停一下
yield return new WaitForSeconds(0.3f);
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
#### 旋转
~~~C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotateSelf : MonoBehaviour
{
//声明一个旋转速度
public float speed=90;//度数
void Update()
{
//通过Rotate方法控制旋转
//只围绕Z轴旋转,xy都为0
transform.Rotate(new Vector3(0, 0,speed * Time.deltaTime));
}
}