1-5 见缝插针

任务1:资源下载

任务2:案例演示

任务3:创建工程和场景

Project Name:StickPin

import素材,为两张png图

创建各个分类文件夹Scenes/ Prefabs/ Scripts

修改Main Camera的Clear Flags为Solid Color
  Background颜色到小清新的卡其色

任务4:创建小球和分数显示

2D游戏 -- 勾选Scene上的2D标识

创建小球:

将Image里的Circle拖入Hierarchy面板
调整位置到中偏上,scale为0.7
颜色为黑

计分板:

UI->Text 用于显示分数
删除自动创建的EventSystem,因为不需要用到事件
Text居中(reset Rect Transform即可)
文字水平居中竖直居中,字体白色,大小变大

Canvas的渲染模式Render Mode改为World Space
  这样就可以将UI缩小到和游戏开发环境一样,便于设计大小
Canvas的Event Camera选择为Main Camera;共用同一个Camera即可
Canvas的大小设置为100*100(因为Text的是100*100)
  但是Canvas和Circle比较还是很大,-> scale 0.01 (之前是1pixel=1m,现在是100pixels=1m)
  将Canvas的位置放在Circle圆心(Position值相同即可)

运行游戏,手动改变分数,发现100分时候只显示10分
  勾选Text的best fit,自适应大小

任务5:控制小球旋转

围绕圆心顺时针匀速旋转 -- 围绕z轴旋转

transform.Rotate(new Vector3(, , -) * speed * Time.deltaTime);

speed 设置为90; // 每秒钟旋转90°

任务6:针的Prefab预制体

创建针 Image->Pin
颜色为黑,大小放大到接近Circle的直径,方向从下往上

创建针头 Image->Circle
成为Pin的子物体
颜色为黑,改变大小,放在针的下端

给针头Circle添加碰撞器Circle Collider 2D

做成Prefab

任务7:开发GameManager生成针(实例化)

创建空物体StartPoint,放置于针准备发射的位置

创建空物体SpawnPoint,放置于针实例化的位置(在屏幕外部)

创建空物体GameManager,用于管理针的实例化
  创建GameManager.cs
  控制针的发射:

得到两个点的位置:

private Transform startPoint;
private Transform spawnPoint;

startPoint = GameObject.Find("StartPoint").transform;
spawnPoint = GameObject.Find("SpawnPoint").transform;

得到Prefab:

public GameObject pinPrefab; // 拖拽赋值

实例化针:

GameObject.Instantiate( pinPrefab, spawnPoint.position, pinPrefab.transform.rotation);

public class GameManager : MonoBehaviour {

    public GameObject pinPrefab;private Transform spawnPoint;

    // Use this for initialization
void Start() {
spawnPoint = GameObject.Find("SpawnPoint").transform;
SpawnPin();
} private void SpawnPin() {
GameObject.Instantiate(pinPrefab, spawnPoint.position, pinPrefab.transform.rotation);
}
}

任务8&9&10:控制针移动到准备位置 & 针的插入 & 判断针到达表面

给Pin添加脚本PinMovement.cs来控制针的初始运动

Pin的运动分为两段:1. 准备阶段;2. 插针阶段
  用bool hasReachedStartPoint = false; 来判断是否到达StartPoint
  用bool isInserting = false; 来判断是否在插针阶段

1. 准备阶段

private Transform startPoint; // 获取该Transform与上任务相同

逻辑思路:
  if(isInserting == false) {
    if(hasReachedStartPoint == false) {  // 准备阶段
      transform.position = Vector3.MoveTowards
        (transform.position, startPoint.position, speed * Time.deltaTime);
      // MoveTowards(起点,终点,速度) 返回一个Vector3的位置信息
    }
  }

2. 判断是否到达StartPoint

Vector3.Distance(transform.position, startPoint.position) < 0.05f;
// Vector3.Distance(两点坐标),返回的是两点之间的距离

如果到达,hasReachedStartPoint = true;

3. 插针阶段

检测鼠标左键的按下
  Input.GetMouseButtonDown(0);

发射针:
  private PinMovement currentPin;
  实例化的时候currentPin得到Pin的实体(赋值给currentPin即可)
    currentPin = GameObject.Instantiate(..).GetComponent<PinMovement>();
  currentPin.StartInsert();

  StartInsert() {
    isInserting = true;
    hasReachedStartPoint = true;
  }

朝着Circle运动:
  得到Circle的位置 private Transform... = GameObject.Find(...);
  transform.position = Vector3.MoveTowards(...);

运行,点击鼠标,Pin insert了,但是在一个奇怪的位置停住了

发现针头的名字也是Circle,怀疑得到的是这个Circle的坐标,将其改为PinHead

还是不对,将脚本中Circle设置为public,运行游戏,双击Unity里的public Circle,发现这个Circle的属性和PinHead的属性相同,但是不知道怎么改。。。故使用FindGameObjectWithTag("Circle");实现

成功运行了。但是将代码改回Find("Circle")后发现,也成功运行了。不知道为何。有点懵逼。

4. 判断是否到达目标位置(是否插入Circle)

同样用Vector3.Distance()判断

在Unity中手动计算针在到达小球表面时候针和小球原点的距离

private Vector3 targetPosition = circleTransform.position - Vector3(0, diff,0);
if(Vector3.Distance(transform.position, targetPosition) < 0.05f) {
  transform.position = targetPosition; // 最后位置的到达
  transform.parent = circle; // 让针随着小球转动
  isInserting = false;
}

void Update () {
if (isInserting == false) {
if (hasReachedStartPoint == false) { // 准备阶段
transform.position = Vector3.MoveTowards(transform.position, startPoint.position, speed * Time.deltaTime);
// MoveTowards(起点,终点,速度) 返回一个Vector3的位置信息
if (Vector3.Distance(startPoint.position, transform.position) < 0.05f) {
transform.position = startPoint.position;
hasReachedStartPoint = true; // 到达以后transform就不变了,除非isInserting == true
}
}
} else {
// 插针阶段
transform.position = Vector3.MoveTowards(transform.position, targetPosition, speed * Time.deltaTime);
if (Vector3.Distance(transform.position, targetPosition) < 0.05f) {
transform.position = targetPosition; // 最后位置的到达
transform.parent = circleTransform; // 让针随着小球转动
isInserting = false; // 到达小球表面,isInserting == false; hasReached == true; 不会执行代码
}
}
} public void StartInsert() {
isInserting = true;
hasReachedStartPoint = true;
}

任务10:针的连环发射

在点击鼠标左键的时候,StartInsert();之后进行SpawnPin();即可

针的运动速度有点慢,修改为15

void Update() {  // GameManager.csif (Input.GetMouseButtonDown()) {
currentPin.StartInsert();
SpawnPin();
}
}

任务11:针头的碰撞和游戏结束

触发检测

针头有了Collider,但是没有刚体组件
  添加Rigidbody2D,重力Gravity Scale设置为0
  并使用Trigger模式(不想让碰撞影响运动)

如果两个针头碰撞,游戏结束

给PinHead添加Tag "PinHead",方便Trigger的检测

PinHeadCollision.cs
  void OnTriggerEnter2D(Collider2D collier) {
    if(collider.tag == "PinHead") {
      // 调用GameManager的方法
      GameObject.Find("GameManager").
        GetComponent<GameManager>().GameOver();
    }
  }

GameManager.GameOver():

// 因为每个PinHead上都会有PinHeadCollision的脚本,所以Collision发生的时候会执行多次GameOver(),而实际上执行一次即可

private bool isGameOver = false;

public void GameOver() {
  if(isGameOver) return;
  // 游戏结束后小球不旋转了
  GameObject.Find("Circle").GetComponent<RotateSelf>().enabled = false;
  isGameOver = true;

  }

在Update()中,游戏结束后就不能控制Pin了

Update() {
  if(isGameOver) return;
  ...
}

任务12:控制分数的显示

private int score = 0;
public Text scoreText;  // using UnityEngine.UI;

// 在按下鼠标的时候加分
scoreText.text = score.ToString();

void Update() { // GameManager.cs
if (isGameOver) return;
if (Input.GetMouseButtonDown()) {
currentPin.StartInsert();
score++;
scoreText.text = score.ToString();
SpawnPin();
}
}

任务13:游戏结束动画的显示

思路:
  游戏背景颜色改变
  Camera size变小(画面变近)

GameManager.cs

IEnumerator GameOverAnimation() {  // using System.Collections;
  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.5f); // 暂停0.5s(因为播放完动画会自动重新开始游戏)
  // using UnityEngine.SceneManagement
  SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);  // 重载游戏
}

// Lerp(起始值,目标值,改变速度) -- 渐变

在GameOver()中加入StartCoroutine(GameOverAnimation());调用;

(将circle旋转速度改为140,可玩性更强一些)

   

Siki_Unity_1-5_见缝插针的更多相关文章

  1. HTML5小游戏之见缝插针

    今天给大家带来的就是一款叫做<见缝插针>的游戏.有空你就往里插,直到你无处可插!看你能过多少关! 简洁大气 黑白搭配游戏画面非常的简洁,米白色的背景中央,放置着一个不断旋转的太阳状的球体, ...

  2. H5游戏见缝插针开发

    中秋节马上就要来临,公司开发了一个h5小游戏叉月饼,其实就是游戏“见缝插针”的翻版.这个游戏的开发任务落到了我的头上... 一 游戏介绍 游戏场景基本如下所示:         二 所用工具 这次的开 ...

  3. python学习笔记5_异常

    python学习笔记5_异常 1.什么事异常 Python使用异常对象(exception object) 来表示异常情况.遇到错误会发生异常. 如果异常对象未被处理或被捕捉,程序就会用所谓的回溯(t ...

  4. Unity 3D游戏-见缝插针源码

    Unity见缝插针功能实现 本文提供全流程,中文翻译.Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) 1 Sphere Rotatio ...

  5. ca12a_c++顺序容器的操作5_访问容器中的数据元素

    ca12a_c++顺序容器的操作5_访问容器中的数据元素访问元素:c.back()..显示最后一个数据c.front() ..显示第一个数据c[n],n就是下标,适合vector与dequec.at( ...

  6. java基础5_数组

    一 数组是一个多个相同数据的集合.数组的长度一旦定义,将不能改变.数组的下标是从0开始的,到数组的长度-1结束. 1.数组的声明,初始化 int[] a = new int[3]{1,2,3}; in ...

  7. re正则表达式5_*

    *表示匹配[0,正无穷大]次 * means math zero or more-----occur any number of times in the text. # -*- coding: ut ...

  8. Deep Learning 5_深度学习UFLDL教程:PCA and Whitening_Exercise(斯坦福大学深度学习教程)

    前言 本文是基于Exercise:PCA and Whitening的练习. 理论知识见:UFLDL教程. 实验内容:从10张512*512自然图像中随机选取10000个12*12的图像块(patch ...

  9. OAF_文件系列5_实现OAF解析XML文件javax.xml.parsers(案例)

    20150729 Created By BaoXinjian

随机推荐

  1. Redis(RedisTemplate)使用hash哈希

    RedisTemplate配置:https://www.cnblogs.com/weibanggang/p/10188682.html package com.wbg.springRedis.test ...

  2. DHCP, NAT

    DHCP Dynamic Host Configuration Protocol(动态主机配置协议) (RFC 2131) Bootstrap Protocol BOOTP(引导程序协议) allow ...

  3. 二、HDFS 架构

    源自:http://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html HDFS has a m ...

  4. mysql update 子查询锁表问题

    mysql在Update带有子查询的时候,子查询的表会锁住,导致该表无法使用.比如 update A set comments = (select count(1) from B where id = ...

  5. IOS中Hybird实现

    现在Hybird这块,网上也有很多文章,最近研究了下,分享给大家. 什么是Hybird技术? 1.一般是指WebView和Native技术混合而成的一套技术方案 2.也可以理解成,非Native技术与 ...

  6. 如何编写及运行JS

    JS也是一种脚本语言,他可以有两种方式在HTML页面进行引入,一种是外联,一种是内部.       外联JS的写法为: <script src="相对路径"></ ...

  7. Excel2013打开提示 文件格式和扩展名不匹配。文件可能已损坏或不安全。除非您信任其来源,否则请勿打开。是否仍要打开它?

    有的时候打开xls文档时,会提示“文件格式和扩展名不匹配.文件可能已损坏或不安全.除非您信任其来源,否则请勿打开.是否仍要打开它?” 遇到这种情况,我们需要 1.win键+R键,打开“运行“,输入re ...

  8. MySQL必知必会 读书笔记二:MySQL使用

    使用MySQL 选择数据库 使用USE关键字 USE database; 了解数据库和表 如果不知道可以使用的数据库名时,可用MySQL的SHOW命令来显示这些信息. SHOW DATABASES; ...

  9. Python入门 —— 02基础语法

    基础语法入门学习推荐: 简明 Python 教程 下文仅为入门推荐书籍的补充与重点 多行语句:末尾使用斜杠 (  ) ,将一行分为多行 var = item1 + item2 + item3 注释: ...

  10. 论反向ajax

    在讨论反向ajax之前,说一下我大二写的一个聊天程序,通过前端ajax不断向服务器发送请求(通过http连接),服务器进行一次数据库查询,然后返回结果,断开与服务器的链接(绝大部分都是无用的结果)来维 ...