引言:人生无处不代码,无代码处不人生。小生作为U3D学习之旅中的一员,将基础案例主要开发流程记录下来,与共同兴趣的你分享。
开发版本:unity 5.3.5f
适合人群:初学Unity者
源文件链接请见文末!
开启学习之旅吧!
创建2D工程StickPin,并创建新场景MainScene,导入素材,完成初始场景搭建
注意工程路径最好不要有中文
在Circle身上挂载脚本RotateSelf.cs,控制圆圈顺时针旋转
public class RotateSelf : MonoBehaviour {
public int speed = 90;
private void Update()
{
//方法一:
transform.Rotate(-Vector3.forward,speed*Time.deltaTime);
//方法二:
//transform.Rotate(-new Vector3(0, 0, speed * Time.deltaTime));
//方法三:
//transform.Rotate(0, 0, -speed * Time.deltaTime);
}
}
制作针,并设为预制体Pin
PinHead设为Pin的子物体,并设置标签PinHead
为针头添加Rigidbody 2D,Circle Collider 2D组件,并设置Gravity Scale为0,勾选Is Trigger
注意,collider需要加上Rigidbody才能完成触发检测
创建两个空对象,StartPoint作为发射针的位置,SpawnPoint作为生成针的位置
在Pin身上挂载脚本Pin.cs
新建方法PinMove
需要注意目标圆的位置targetCirclePos要加一个偏差值,防止针被圆挡住
在Start()方法中完成初始化
private void Start()
{
//GameObject.FindWithTag()需要给对象设置相应标签
targetTf = GameObject.FindWithTag("StartPoint").transform;
circle = GameObject.FindWithTag("Circle").transform;
//偏差值可以根据实际情况调节
targetCirclePos = circle.position - new Vector3(0, 1.47f, 0);
}
在Update()方法中调用PinMove()方法
private void Update()
{
PinMove();
}
private void PinMove()
{
//isFly判断是否从准备位置StartPoint发射
if (isFly == false)
{
//isReach判断是否从生成位置SpawnPoint移动至发射位置
if (isReach == false)
{
//Vector3.MoveTowards()方法将物体从当前位置直线移动到目标位置
transform.position = Vector3.MoveTowards(transform.position, targetTf.position, speed * Time.deltaTime);
}
//Vector3.Distance()判断两点之间的距离
//如果针的当前位置距离发射位置小于0.05,则停止运动
if (Vector3.Distance(transform.position, targetTf.position) < 0.05f)
{
transform.position = targetTf.position;
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.SetParent(circle);
isFly = false;
}
}
}
新建公共方法StartFly()
//用于外部调用,设置针的发射状态
public void StartFly()
{
isFly = true;
isReach = true;
}
在PinHead上挂载脚本PinHead.cs
public class PinHead : MonoBehaviour
{
//OnTriggerEnter2D在is Trigger勾选下才能起作用,用于2D触发检测
private void OnTriggerEnter2D(Collider2D collision)
{
//如果碰撞物体的tag标签为PinHead,说明碰到其他的针头了
if (collision.CompareTag("PinHead"))
{
// GameObject.Find()根据物体名称,找到GameManager物体
//GetComponent获取对象身上GameManager组件,调用GameOver方法
GameObject.Find("GameManager").GetComponent().GameOver();
}
}
}
新建空对象GameManager,挂载脚本GameManager.cs
创建新方法SpawnPin(),用于生成针,并获得针身上挂载的Pin脚本
void SpawnPin()
{
//GameObject.Instantiate()新生成的对象类型为Object,所以需要强转为GameObject类型
GameObject pin = GameObject.Instantiate(pinPrefabs, spawnPoint.position, pinPrefabs.transform.rotation) as GameObject;
//GetComponent用于获取对象的组件,组件名写在<>内
currentPin = pin.GetComponent();
}
新建一个方法GamOver(),用于结束游戏操作
public void GameOver()
{
//防止两球碰撞,多次调用GameOver方法
if (isGameOver) return;
//enabled设为false,则组件失效,圆不能再旋转
GameObject.FindWithTag("Circle").GetComponent().enabled = false;
isGameOver = true;
}
在Update()方法类调用SpawnPin方法,鼠标左键点击时,发射当前针,并生成新的针
private void Update()
{
//isGameOVer为false,则游戏结束,直接返回,不再执行下面命令
if (isGameOver) return;
//Input.GetMouseButtonDown(0)监听鼠标左键点击事件
if (Input.GetMouseButtonDown(0))
{
//调用针的StartFly方法,设置针发射
currentPin.StartFly();
//当前针发射后,再生成针,完成连续发射功能
SpawnPin();
}
}
控制分数显示,设置两个全局变量,注意需要引入命名空间using UnityEngine.UI;
public Text scoreText;
public int score;
可以在Inspector面板完成赋值
在Update方法内添加,如下加粗语句,完成分数的增加和显示
if (Input.GetMouseButtonDown(0))
{
//score自增1
score++;
//ToString()将数值score转为字符串
scoreText.text = score.ToString();
//调用针的StartFly方法,设置针发射
currentPin.StartFly();
//当前针发射后,再生成针,完成连续发射功能
SpawnPin();
}
使用协程实现场景结束效果
//IEnumerator(迭代器)
IEnumerator GameOverAnimation()
{
while (true)
{
//Lerp线性插值运算,以此实现渐变效果
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;
}
//完成循环后,等待0.2秒
yield return new WaitForSeconds(0.2f);
//重新加载当前场景
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
需要在GameOver()方法内开启协程
public void GameOver()
{
if (isGameOver) return;
GameObject.FindWithTag("Circle").GetComponent().enabled = false;
//开启协程
StartCoroutine(GameOverAnimation());
isGameOver = true;
}
在MainCamera上添加组件AudioSource,audioclip设置背景音乐,勾选play on awake,loop选项
Volume控制音量,适量调节
在GameManager.cs中
添加public AudioClip clip,inspector面板中赋值
Update()方法中添加AudioSource.PlayClipAtPoint
if (Input.GetMouseButtonDown(0))
{
score++;
scoreText.text = score.ToString();
currentPin.StartFly();
AudioSource.PlayClipAtPoint(clip,Camera.main.transform.position);
SpawnPin();
}
File-BuildSettings 点击Build完成打包,注意打包出的文件要放在同一个文件夹内
至此,见缝插针基础案例开发完成,为了督促自己学习,以后会陆续写一些博客,帮助更多和我一样喜欢游戏开发的同学!
素材及工程文件百度云链接:链接:https://pan.baidu.com/s/1qZqBdYO 密码:3u1t