unity3d可以建模吗2d保龄球游戏加点其他的功能怎么实现

unity3d保龄球游戏源码Bowling Starter Kit,Unity3D,游戏源码,6m5m游戏素材
请求处理中...
unity3d保龄球游戏源码Bowling Starter Kit,支持移动设备,c#脚本,含音乐和AI对手,支持多人,支持高中低端设备。The Bowling Starter Kit easily allows you to create a bowling game.sc ripts are written in c#, with comments.Features: ->Mobile Ready->1 Music Track->1 Ambient Noise Track->2 Player Multiplayer ready->AI opponent ->Scalable graphics for high medium or& low end devices
或 0 积分 ()
下载449浏览人数4072交付方式直接下载
免责声明:【1】资源来自网络,仅限于个人学习研究,请勿用于任何商业用途,请支持或购买正版,尊重版权,请严格遵守国家相关著作版权保护的法律和规则,请下载24小时内务必删除,否则后果自负,本站不承担任何责任及连带责任!【2】本站为学习平台,所分享的资源以学习为目的,并不能保证所有源码人人都能编译,因素太多,旨在学习参考,无任何技术支持,如果您要求完美或追求细节,请勿下载,大家都不容易,互相理解,才能让更多好的学习资源出现!【3】部分素材压缩包因体积过大而上传到百度等网盘上,如果发现在本站下载的压缩包只要有几K大小,说明该压缩包里只是网盘的下载链接,并非文件损坏,本站的所有素材都是经过了审核,大家可放心下载,欢迎监督反馈。【4】做个好平台真心不容易,我们一直在努力,因本站素材量大,难免会出现某网盘下载链接失效等问题,请大家及时反馈,我们会及时修正保证您可以拿到素材,请大家支持和理解!
免责声明:本网所展示的素材与服务信息由买卖双方自行提供,其真实性、准确性和合法性由信息发布人负责。本网不提供任何保证,并不承担任何法律责任,如有不妥之处请及时反馈,本网将会妥善处理。
友情提醒:本站旨在游戏开发的学习,所分享的素材资源均来源于网络,仅适用于学习参考,尊重版权,禁止用于任何商业用途,否则后果自负,所展示的素材版权归原作者或公司所有,如果本站素材侵犯了您的权益,请联系我们,我们将及时处理。
猜您喜欢的游戏素材
0金币 / 份
1金币 / 个
1金币 / 个
0金币 / 个
1金币 / 个
0金币 / 个
0金币 / 个
2金币 / 个
0金币 / 个
1金币 / 个
好评率99.23%保龄球游戏Demo
时间: 20:20:50
&&&& 阅读:568
&&&& 评论:
&&&& 收藏:0
标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&记录的一个简单课后作业...
1、分析需求文案策划
&阅读Unity3D保龄球案例设计和积分规则,最后整理游戏规则:
2、搭建游戏场景
导入场景资源包,发现运行资源包的场景发现报错,原因大体是因为网格内陷导致网格碰撞器出现了些小问题,这通常出现在早期Unity版本资源包。
通过勾选每个保龄球的Collider中Convex选项,将不报错。
加载各种模型资源,一系列的操作,最后搭建将场景搭建完毕。把所有的保龄球放在一个AllBowls空物体下,把AllBowls和ball制作成一个预制体。
&3、编写保龄球的控制脚本
新建一个BallController.cs脚本组件,用来管理球的发射方法。普通情况下,正常情况玩保龄球,会有以下几种操作:
带球到到发球线
给球施加一个方向的力
用射线的方式可以达到需求,但是具体如何实现还得需要分析:
我们可以通过射线找到两个关键点扔球点和发球点,两点确定发球方向。在扔球点捡起球,在发球点发射。
根据场景我选择世界坐标Z=8这个轴作为发球面,这有很大的瑕疵,以后会逐渐修正。
BallController.cs代码:
1 using System.C
2 using System.Collections.G
3 using UnityE
4 /// &summary&
5 /// 保龄球的控制
6 /// &/summary&
7 public class BallController : MonoBehaviour
<span style="color: #
#region 射线相关
<span style="color: #
<span style="color: #
/// &summary&
<span style="color: #
/// 射线碰撞信息
<span style="color: #
/// &/summary&
<span style="color: #
private RaycastH
<span style="color: #
/// &summary&
<span style="color: #
/// 图层遮罩
<span style="color: #
/// &/summary&
<span style="color: #
private LayerM
<span style="color: #
/// &summary&
<span style="color: #
/// 球的位置
<span style="color: #
/// &/summary&
<span style="color: #
public Transform ballT
<span style="color: #
<span style="color: #
#endregion
<span style="color: #
<span style="color: #
/// &summary&
<span style="color: #
/// 推力范围
<span style="color: #
/// &/summary&
<span style="color: #
public Transform pushA
<span style="color: #
/// &summary&
<span style="color: #
/// 球的半径
<span style="color: #
/// &/summary&
<span style="color: #
[SerializeField]
<span style="color: #
private float ballR
<span style="color: #
/// &summary&
<span style="color: #
/// 扔球点
<span style="color: #
/// &/summary&
<span style="color: #
private Vector3 ballPushO
<span style="color: #
/// &summary&
<span style="color: #
/// 球左右方向差量
<span style="color: #
/// &/summary&
<span style="color: #
private Vector3 ballPushD
<span style="color: #
<span style="color: #
//是否推出去
<span style="color: #
static bool pushed = false;
<span style="color: #
private void Start()
<span style="color: #
<span style="color: #
//获取球的半径
<span style="color: #
ballRadius = ballTrans.GetComponent&SphereCollider&().
<span style="color: #
GetComponent&Rigidbody&().isKinematic =true;
<span style="color: #
<span style="color: #
<span style="color: #
private void Update()
<span style="color: #
<span style="color: #
//发射一条射线
<span style="color: #
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
<span style="color: #
//如果还没有推出去这个球
<span style="color: #
if (!pushed)
<span style="color: #
<span style="color: #
//推球逻辑
<span style="color: #
if (Physics.Raycast(ray, out hit, <span style="color: #00, LayerMask.GetMask("AreaFloor")))
<span style="color: #
<span style="color: #
<span style="color: #
Vector3 _ballPushTrans = new Vector3(hit.point.x, <span style="color: #.558f + ballRadius * <span style="color: #.01f, <span style="color: #.026f);
<span style="color: #
if (hit.transform == pushArea)
<span style="color: #
<span style="color: #
_ballPushTrans = new Vector3(hit.point.x, hit.point.y + <span style="color: #.3f, hit.point.z);//球的位置
<span style="color: #
ballTrans.position = _ballPushT
<span style="color: #
ballPushOrgin = hit. ;//记录球的起点
<span style="color: #
//Debug.Log(hit.point.x + "," + hit.point.y + "," + hit.point.z);
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
if (!pushed && hit.point.z & 8f && ballPushOrgin != Vector3.zero)//捡起保龄球并且它的发射距离超过世界坐标Z=8f(没有)
<span style="color: #
<span style="color: #
Vector3 _ballPushDir = hit.//记录一下球的终点
<span style="color: #
Debug.Log(ballPushOrgin);
<span style="color: #
ballPushDir = _ballPushDir - ballPushO
<span style="color: #
pushed = true;
<span style="color: #
ballTrans.position = new Vector3(hit.point.x, <span style="color: #.558f + ballRadius * <span style="color: #.01f, <span style="color: #.026f);
<span style="color: #
GetComponent&Rigidbody&().isKinematic = false;
<span style="color: #
ballTrans.GetComponent&Rigidbody&().AddForce((transform.forward + ballPushDir) * <span style="color: #, ForceMode.Impulse);
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: # }
BallController.cs
到现在为止发球功能可以实现。
4、每球得分计算
新建一个Bowl.cs脚本组件,检测得分情况。让每个保龄球均挂载该组件。
关于如何判断这个保龄球是否倒了,选择使用transform.localRotation中X和Z属性,如果他们的绝对值大于0.3f,我们就认为这个保龄球倒了。当然我们可以有其他更好的方法,比如碰撞器和触发器,不过通过计算网格的接触点,这会稍微增加一点小小的性能消耗,这个方法会更精准但是我们并不需要这么精准的操作。
Bowl.cs代码如下:
1 using System.C
2 using System.Collections.G
3 using UnityE
4 /// &summary&
5 /// 保龄球
6 /// &/summary&
7 public class Bowl : MonoBehaviour
/// &summary&
<span style="color: #
/// 是否得分
<span style="color: #
/// &/summary&
<span style="color: #
public bool GetS
<span style="color: #
<span style="color: #
private void FixedUpdate()
<span style="color: #
<span style="color: #
if (!GetScore)
<span style="color: #
<span style="color: #
if (Mathf.Abs(transform.localRotation.x) & <span style="color: #.3f || Mathf.Abs(transform.localRotation.z) & <span style="color: #.3f)
<span style="color: #
<span style="color: #
<span style="color: #
GetScore = true;
<span style="color: #
Debug.LogWarning("分数加+1");
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: # }
&最后运行测试一下:
5、UI统计分数面板
&UI的搭建选择使用UGUI,首先建立一个新画布和相机,修改命名。
对Player_UI_Camera和Player_UI_Canvas进行调整,以适应场景。
接下来就是UI界面搭建。
新建一个脚本GameManage.cs组件,用来游戏管理。挂载到Player_UI_Panel对象上。可是如何进行游戏管理?把所有的UIText设置更新都写在GameManage.cs里?这无疑对GamManage.cs产生较大的功能负担,所以我们新建的GameManage.cs先不编辑,建一个ScoreItem.cs类,这个东西负责统计存储和修改每轮分数。然后让GameManage去管理它。
编写ScoreItem.cs:
1 using System.C
2 using System.Collections.G
3 using UnityE
4 using UnityEngine.UI;
6 public class ScoreItem : MonoBehaviour
/// &summary&
/// 所有分数文字
<span style="color: #
/// &/summary&
<span style="color: #
public Text[] SocreT
<span style="color: #
/// &summary&
<span style="color: #
/// 每轮分数
<span style="color: #
/// &/summary&
<span style="color: #
[SerializeField]
<span style="color: #
private int[] S
<span style="color: #
/// &summary&
<span style="color: #
/// 本轮分数总和
<span style="color: #
/// &/summary&
<span style="color: #
public int AllScoreItemN
<span style="color: #
/// &summary&
<span style="color: #
/// 本轮全中?
<span style="color: #
/// &/summary&
<span style="color: #
public bool isStrike = false;
<span style="color: #
/// &summary&
<span style="color: #
/// 本轮补中?
<span style="color: #
/// &/summary&
<span style="color: #
public bool isSpare = false;
<span style="color: #
<span style="color: #
public void Start()
<span style="color: #
<span style="color: #
Scores = new int[SocreTexts.Length - <span style="color: #];//每轮分数初始化
<span style="color: #
<span style="color: #
/// &summary&
<span style="color: #
/// 每轮分数设置索引为_index的分数文本的值为_score
<span style="color: #
/// &/summary&
<span style="color: #
/// &param name="_index"&SocreTexts索引&/param&
<span style="color: #
/// &param name="_score"&分数&/param&
<span style="color: #
public void SetScoreText(int _index, int _score)
<span style="color: #
<span style="color: #
Scores = new int[SocreTexts.Length];//更新设置分数
<span style="color: #
Scores[_index] = _//更新并存储分数
<span style="color: #
AllScoreItemNum = <span style="color: #;
<span style="color: #
foreach (var item in Scores)
<span style="color: #
<span style="color: #
AllScoreItemNum +=//累加本轮分数总和
<span style="color: #
<span style="color: #
<span style="color: #
/// &summary&
<span style="color: #
/// 显示所有分数
<span style="color: #
/// &/summary&
<span style="color: #
public void ShowScore()
<span style="color: #
<span style="color: #
//设置每轮
<span style="color: #
for (int i = <span style="color: #; i & SocreTexts.Length - <span style="color: #; i++)
<span style="color: #
<span style="color: #
SocreTexts[i].text = Scores[i].ToString();
<span style="color: #
<span style="color: #
SocreTexts[SocreTexts.Length - <span style="color: #].text = AllScoreItemNum.ToString();//总分设置
<span style="color: #
<span style="color: #
<span style="color: # }
ScoreItem.cs
&我们为每个ScoreItem(前九局)和FinalScore(最后一局)这些对象都挂载ScoreItem.cs组件并绑定每个ScoreItem中的ScoreTexts。
其中ScoreItem(前九局)绑定每个子对象的文本对象如下:
最后一个FinalScore绑定如下:
绑定完毕后,我们只要获取每个ScoreItem就能直接更新每局数据了。所以我们要在GameManage内编写这些对象的引用,GameManage只有一个,所以我们可以把它单例,全局调用,SocreItems数组存储每局ScoreItem。我们先简单编写GameManage一下:
1 using System.C
2 using System.Collections.G
3 using UnityE
4 using UnityEngine.UI;
6 public class GameManage : MonoBehaviour
#region 单例
<span style="color: #
private static GameManage _I
<span style="color: #
/// &summary&
<span style="color: #
/// 游戏管理单例
<span style="color: #
/// &/summary&
<span style="color: #
public static GameManage Instacne
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
private void Awake()
<span style="color: #
<span style="color: #
_Instacne = this;
<span style="color: #
<span style="color: #
#endregion
<span style="color: #
/// &summary&
<span style="color: #
/// 每局分数块游戏对象
<span style="color: #
/// &/summary&
<span style="color: #
public ScoreItem[] SocreI
<span style="color: #
<span style="color: #
/// &summary&
<span style="color: #
/// 每球的临时得分
<span style="color: #
/// &/summary&
<span style="color: #
public int _tempS
<span style="color: #
<span style="color: #
/// &summary&
<span style="color: #
/// 保龄球瓶预制体
<span style="color: #
/// &/summary&
<span style="color: #
public GameObject bowlsP
<span style="color: #
<span style="color: #
/// &summary&
<span style="color: #
/// 保龄球控制预制体
<span style="color: #
/// &/summary&
<span style="color: #
public BallController ballC
<span style="color: #
<span style="color: #
<span style="color: # }
GameManage.cs
&把刚才的ScoreItem那些组件绑定,并顺手绑定一下BowlsPrefabs:
&绑定结束。
修改重新修改一下Bowl然后再发射一球
1 public class Bowl : MonoBehaviour
/// &summary&
/// 是否得分
/// &/summary&
public bool GetS
private void FixedUpdate()
<span style="color: #
if (!GetScore)
<span style="color: #
<span style="color: #
if (Mathf.Abs(transform.localRotation.x) & <span style="color: #.3f || Mathf.Abs(transform.localRotation.z) & <span style="color: #.3f)
<span style="color: #
<span style="color: #
<span style="color: #
GetScore = true;
<span style="color: #
GameManage.Instacne._tempScore++;//这轮分数
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: # }
&测试一下,已经清晰的看见GameManage的TempScore变量=6,也就是这一球得分:
&6、刷新出球
发球得分已经可以获取到了,那么接下来要实现的功能就是如何结束此球结束,开始下一球,不断刷新出球。我们的思路如下:
所以我们重新修改一下GameManage.cs:
#region 单例
private static GameManage _I
/// &summary&
/// 游戏管理单例
/// &/summary&
public static GameManage Instacne
private void Awake()
_Instacne = this;
#endregion
/// &summary&
/// 每局分数块游戏对象
/// &/summary&
public ScoreItem[] SocreI
/// &summary&
/// 每球的临时得分
/// &/summary&
public int _tempS
/// &summary&
/// &/summary&
public Transform roomW
/// &summary&
/// 推力范围
/// &/summary&
public Transform pushA
/// &summary&
/// 保龄球瓶预制体
/// &/summary&
public GameObject bowlsP
/// &summary&
/// 保龄球预制体
/// &/summary&
public GameObject ballP
/// &summary&
/// 保龄球对象
/// &/summary&
public GameO
public BallController _BallC
/// &summary&
/// 出界等待时间
/// &/summary&
[SerializeField]
private float outAreaWaitTime = 5f;
private float _
/// &summary&
/// 每球声明时间
/// &/summary&
[SerializeField]
private float BallLifeTime = 30f;
/// &summary&
/// 滚动时间
/// &/summary&
private float _tempL
private void Start()
CreatBall();
private void Update()
if (ball != null)
if (_BallController.pushed)//球已经被推出去
_tempLife += Time.deltaT
if (_tempLife&BallLifeTime&&!_BallController.isOutArea)//一直没出届
Debug.Log("此球分数:" + _tempScore);
_tempLife = <span style="color: #;
_tempScore = <span style="color: #;//清零
DestroyImmediate(ball);
CreatBall();
if (_BallController.isOutArea)//球出界
_temp += Time.deltaT
if (_temp & outAreaWaitTime)//超过出界时间
Debug.Log("此球分数:" + _tempScore);
_tempLife = <span style="color: #;
_temp = <span style="color: #;//重新计时
_tempScore = <span style="color: #;//清零
DestroyImmediate(ball);
CreatBall();
<span style="color: #0
<span style="color: #1
<span style="color: #2
<span style="color: #3
<span style="color: #4
<span style="color: #5
public void CreatBall()
<span style="color: #6
<span style="color: #7
if (ball == null)
<span style="color: #8
<span style="color: #9
ball = Instantiate(ballPrefab) as GameO
<span style="color: #0
_BallController = ball.GetComponent&BallController&();
<span style="color: #1
_BallController.Inits();
<span style="color: #2
<span style="color: #3
&再绑定一下各值。
稍微修改一下BallController.cs,添加越界的碰撞检测:
#region 射线相关
/// &summary&
/// 射线碰撞信息
/// &/summary&
private RaycastH
/// &summary&
/// 图层遮罩
/// &/summary&
private LayerM
/// &summary&
/// 球的位置
/// &/summary&
public Transform ballT
#endregion
/// &summary&
/// 球的半径
/// &/summary&
[SerializeField]
private float ballR
/// &summary&
/// 扔球点
/// &/summary&
private Vector3 ballPushO
/// &summary&
/// 球左右方向差量
/// &/summary&
private Vector3 ballPushD
/// &summary&
/// 是否推出去
/// &/summary&
public bool pushed = false;
/// &summary&
/// 是否撞墙
/// &/summary&
public bool ishitW
/// &summary&
/// 出界了
/// &/summary&
public bool isOutA
/// &summary&
/// 保龄球初始化
/// &/summary&
public void Inits() {
//获取球的半径
ballRadius = ballTrans.GetComponent&SphereCollider&().
GetComponent&Rigidbody&().velocity = Vector3.
GetComponent&Rigidbody&().isKinematic = true;//不受动力
isOutArea = false;//没有越界
pushed = false;//没有推出去
ishitWall =false;//没有撞墙
private void Update()
//发射一条射线
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//如果还没有推出去这个球
if (!pushed)
//推球逻辑
if (Physics.Raycast(ray, out hit, <span style="color: #00, LayerMask.GetMask("AreaFloor")))
Vector3 _ballPushTrans = new Vector3(hit.point.x, <span style="color: #.558f + ballRadius * <span style="color: #.01f, <span style="color: #.026f);
if (hit.transform == GameManage.Instacne.pushArea)
_ballPushTrans = new Vector3(hit.point.x, hit.point.y + <span style="color: #.3f, hit.point.z);//球的位置
ballTrans.position = _ballPushT
ballPushOrgin = hit. ;//记录球的起点
//Debug.Log(hit.point.x + "," + hit.point.y + "," + hit.point.z);
if (!pushed && hit.point.z & 8f && ballPushOrgin != Vector3.zero)//捡起保龄球并且它的发射距离超过世界坐标Z=8f(没有)
Vector3 _ballPushDir = hit.//记录一下球的终点
Debug.Log(ballPushOrgin);
ballPushDir = new Vector3(_ballPushDir.x - ballPushOrgin.x, <span style="color: #, <span style="color: #);
pushed = true;
ballTrans.position = new Vector3(hit.point.x, <span style="color: #.558f + ballRadius * <span style="color: #.01f, <span style="color: #.026f);
GetComponent&Rigidbody&().isKinematic = false;
ballTrans.GetComponent&Rigidbody&().AddForce((transform.forward + ballPushDir) * <span style="color: #, ForceMode.Impulse);
/// &summary&
/// 碰撞器检测
/// &/summary&
<span style="color: #0
/// &param name="collision"&&/param&
<span style="color: #1
private void OnCollisionEnter(Collision collision)
<span style="color: #2
<span style="color: #3
if (collision.gameObject.layer != <span style="color: # && pushed)
<span style="color: #4
<span style="color: #5
Debug.Log("球出界了!");
<span style="color: #6
isOutArea = true;
<span style="color: #7
<span style="color: #8
&截止到目前为止刷新球的功能没问题了
7、游戏逻辑实现(显示统计每轮得分)
&接下来的几部就实现最后游戏逻辑了,也是最麻烦的。由于前期已经做了较多的功能,所以现在已经减轻了不少代码负担。&
在GameManage.cs定义一个indexItem,记录目前第几轮。
分析一下,如果你开始每一轮第一球打出Strike(10瓶全中),第一轮直接就结束了,但是这一轮的总分还没结束,因为Strike要加下两球的得分。
如果第一球并没有打出Strike,不管第二球打出什么都会结束,第二球如果打出Spare(补中),这一轮的总分也没结束,因为Spare要加下一球的得分;第二球如果没有打出Spare(补中),这一轮的总分就可以算出来了这两球得分之和。
&我们先解决第一轮打球问题,我们在GameManage定义一个方法处理得分情况:
/// &summary&
/// 传递分数
/// &/summary&
/// &param name="_score"&分数值&/param&
public void SetScore(int _score)
if (indexItem & <span style="color: #)//前九轮
if (_tempNumBall == <span style="color: #)//第一球
<span style="color: #
<span style="color: #
SocreItems[indexItem].SetScoreText(<span style="color: #, _score);//设置第一球
<span style="color: #
SocreItems[indexItem].ShowScore();
<span style="color: #
if (_score == <span style="color: #)//分数为10
<span style="color: #
<span style="color: #
<span style="color: #
Debug.LogWarning("Strike全中!");
<span style="color: #
SocreItems[indexItem].isStrike = true;//设置第一球
<span style="color: #
indexItem++;//轮数自加,(indexItem-1)为每局分数块游戏对象SocreItems索引
<span style="color: #
_tempNumBall = <span style="color: #;//开始新的一轮
<span style="color: #
<span style="color: #
else//不为10
<span style="color: #
<span style="color: #
_tempNumBall = <span style="color: #;//开始下一个球
<span style="color: #
<span style="color: #
<span style="color: #
else if (_tempNumBall == <span style="color: #)//第二球
<span style="color: #
<span style="color: #
SocreItems[indexItem].SetScoreText(<span style="color: #, _score);//设置第一球
<span style="color: #
SocreItems[indexItem].ShowScore();
<span style="color: #
if (_score + SocreItems[indexItem].Scores[<span style="color: #] == <span style="color: #)//yi
<span style="color: #
<span style="color: #
<span style="color: #
Debug.LogWarning("Spare补中!");
<span style="color: #
SocreItems[indexItem].isSpare = true;//设置第一球
<span style="color: #
<span style="color: #
indexItem++;//轮数自加,(indexItem-1)为每局分数块游戏对象SocreItems索引
<span style="color: #
_tempNumBall = <span style="color: #;//开始新的一轮
<span style="color: #
<span style="color: #
<span style="color: #
对到目前为止四个核心代码:
1 using System.C
2 using System.Collections.G
3 using UnityE
4 using UnityEngine.UI;
6 public class GameManage : MonoBehaviour
#region 单例
private static GameManage _I
/// &summary&
/// 游戏管理单例
/// &/summary&
public static GameManage Instacne
private void Awake()
_Instacne = this;
#endregion
/// &summary&
/// 每局分数块游戏对象
/// &/summary&
public ScoreItem[] SocreI
/// &summary&
/// 每球的临时得分
/// &/summary&
public int _tempS
/// &summary&
/// &/summary&
public Transform roomW
/// &summary&
/// 推力范围
/// &/summary&
public Transform pushA
/// &summary&
/// 保龄球瓶预制体
/// &/summary&
public GameObject bowlsP
/// &summary&
/// 保龄球预制体
/// &/summary&
public GameObject ballP
/// &summary&
/// 保龄球对象
/// &/summary&
public GameO
public BallController _BallC
/// &summary&
/// 出界等待时间
/// &/summary&
[SerializeField]
private float outAreaWaitTime = 5f;
private float _
/// &summary&
/// 每球声明时间
/// &/summary&
[SerializeField]
private float BallLifeTime = 30f;
/// &summary&
/// 滚动时间
/// &/summary&
private float _tempL
/// &summary&
/// &/summary&
public int indexI
/// &summary&
/// 每轮第N球
/// &/summary&
public int _tempNumB
private void Start()
indexItem = <span style="color: #;
_tempNumBall = <span style="color: #;//第1球
CreatBall();
private void Update()
if (ball != null)
if (_BallController.pushed)//球已经被推出去
_tempLife += Time.deltaT
if (_tempLife & BallLifeTime && !_BallController.isOutArea)//一直没出届
<span style="color: #0
Debug.Log("此球分数:" + _tempScore);
<span style="color: #1
SetScore(_tempScore);
<span style="color: #2
_tempLife = <span style="color: #;
<span style="color: #3
_tempScore = <span style="color: #;//清零
<span style="color: #4
DestroyImmediate(ball);
<span style="color: #5
CreatBall();
<span style="color: #6
<span style="color: #7
if (_BallController.isOutArea)//球出界
<span style="color: #8
<span style="color: #9
_temp += Time.deltaT
<span style="color: #0
if (_temp & outAreaWaitTime)//超过出界时间
<span style="color: #1
<span style="color: #2
Debug.Log("球出界!此球得分:" + _tempScore);
<span style="color: #3
SetScore(_tempScore);
<span style="color: #4
_tempLife = <span style="color: #;
<span style="color: #5
_temp = <span style="color: #;//重新计时
<span style="color: #6
_tempScore = <span style="color: #;//清零
<span style="color: #7
DestroyImmediate(ball);
<span style="color: #8
CreatBall();
<span style="color: #9
<span style="color: #0
<span style="color: #1
<span style="color: #2
<span style="color: #3
<span style="color: #4
public void CreatBall()
<span style="color: #5
<span style="color: #6
if (ball == null)
<span style="color: #7
<span style="color: #8
ball = Instantiate(ballPrefab) as GameO
<span style="color: #9
_BallController = ball.GetComponent&BallController&();
<span style="color: #0
_BallController.Inits();
<span style="color: #1
<span style="color: #2
<span style="color: #3
/// &summary&
<span style="color: #4
/// 传递分数
<span style="color: #5
/// &/summary&
<span style="color: #6
/// &param name="_score"&分数值&/param&
<span style="color: #7
public void SetScore(int _score)
<span style="color: #8
<span style="color: #9
//indexItem++;//轮数自加,(indexItem-1)为每局分数块游戏对象SocreItems索引
<span style="color: #0
if (indexItem & <span style="color: #)//前九轮
<span style="color: #1
<span style="color: #2
if (_tempNumBall == <span style="color: #)//第一球
<span style="color: #3
<span style="color: #4
SocreItems[indexItem].SetScoreText(<span style="color: #, _score);//设置第一球
<span style="color: #5
SocreItems[indexItem].ShowScore();
<span style="color: #6
if (_score == <span style="color: #)//分数为10
<span style="color: #7
<span style="color: #8
<span style="color: #9
Debug.LogWarning("Strike全中!");
<span style="color: #0
SocreItems[indexItem].isStrike = true;//设置第一球
<span style="color: #1
indexItem++;//轮数自加,(indexItem-1)为每局分数块游戏对象SocreItems索引
<span style="color: #2
_tempNumBall = <span style="color: #;//开始新的一轮
<span style="color: #3
<span style="color: #4
else//不为10
<span style="color: #5
<span style="color: #6
_tempNumBall = <span style="color: #;//开始下一个球
<span style="color: #7
<span style="color: #8
<span style="color: #9
else if (_tempNumBall == <span style="color: #)//第二球
<span style="color: #0
<span style="color: #1
SocreItems[indexItem].SetScoreText(<span style="color: #, _score);//设置第一球
<span style="color: #2
SocreItems[indexItem].ShowScore();
<span style="color: #3
if (_score + SocreItems[indexItem].Scores[<span style="color: #] == <span style="color: #)//yi
<span style="color: #4
<span style="color: #5
<span style="color: #6
Debug.LogWarning("Spare补中!");
<span style="color: #7
SocreItems[indexItem].isSpare = true;//设置第一球
<span style="color: #8
<span style="color: #9
indexItem++;//轮数自加,(indexItem-1)为每局分数块游戏对象SocreItems索引
<span style="color: #0
_tempNumBall = <span style="color: #;//开始新的一轮
<span style="color: #1
<span style="color: #2
<span style="color: #3
<span style="color: #4 }
GameManage.cs
1 using System.C
2 using System.Collections.G
3 using UnityE
4 /// &summary&
5 /// 保龄球
6 /// &/summary&
7 public class Bowl : MonoBehaviour
/// &summary&
<span style="color: #
/// 是否得分
<span style="color: #
/// &/summary&
<span style="color: #
public bool GetS
<span style="color: #
/// &summary&
<span style="color: #
/// 瓶号索引
<span style="color: #
/// &/summary&
<span style="color: #
public int I
<span style="color: #
<span style="color: #
private void FixedUpdate()
<span style="color: #
<span style="color: #
if (!GetScore)
<span style="color: #
<span style="color: #
if (Mathf.Abs(transform.localRotation.x) & <span style="color: #.3f || Mathf.Abs(transform.localRotation.z) & <span style="color: #.3f)
<span style="color: #
<span style="color: #
<span style="color: #
GetScore = true;
<span style="color: #
GameManage.Instacne._tempScore++;//这轮分数
<span style="color: #
<span style="color: #
<span style="color: #
1 using System.C
2 using System.Collections.G
3 using UnityE
4 /// &summary&
5 /// 保龄球的控制
6 /// &/summary&
7 public class BallController : MonoBehaviour
#region 射线相关
/// &summary&
/// 射线碰撞信息
/// &/summary&
private RaycastH
/// &summary&
/// 图层遮罩
/// &/summary&
private LayerM
/// &summary&
/// 球的位置
/// &/summary&
public Transform ballT
#endregion
/// &summary&
/// 球的半径
/// &/summary&
[SerializeField]
private float ballR
/// &summary&
/// 扔球点
/// &/summary&
private Vector3 ballPushO
/// &summary&
/// 球左右方向差量
/// &/summary&
private Vector3 ballPushD
/// &summary&
/// 是否推出去
/// &/summary&
public bool pushed = false;
/// &summary&
/// 是否撞墙
/// &/summary&
public bool ishitW
/// &summary&
/// 出界了
/// &/summary&
public bool isOutA
/// &summary&
/// 保龄球初始化
/// &/summary&
public void Inits() {
//获取球的半径
ballRadius = ballTrans.GetComponent&SphereCollider&().
GetComponent&Rigidbody&().velocity = Vector3.
GetComponent&Rigidbody&().isKinematic = true;//不受动力
isOutArea = false;//没有越界
pushed = false;//没有推出去
ishitWall =false;//没有撞墙
private void Update()
//发射一条射线
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//如果还没有推出去这个球
if (!pushed)
//推球逻辑
if (Physics.Raycast(ray, out hit, <span style="color: #00, LayerMask.GetMask("AreaFloor")))
Vector3 _ballPushTrans = new Vector3(hit.point.x, <span style="color: #.558f + ballRadius * <span style="color: #.01f, <span style="color: #.026f);
if (hit.transform == GameManage.Instacne.pushArea)
_ballPushTrans = new Vector3(hit.point.x, hit.point.y + <span style="color: #.3f, hit.point.z);//球的位置
ballTrans.position = _ballPushT
ballPushOrgin = hit. ;//记录球的起点
//Debug.Log(hit.point.x + "," + hit.point.y + "," + hit.point.z);
if (!pushed && hit.point.z & 8f && ballPushOrgin != Vector3.zero)//捡起保龄球并且它的发射距离超过世界坐标Z=8f(没有)
Vector3 _ballPushDir = hit.//记录一下球的终点
Debug.Log(ballPushOrgin);
ballPushDir = new Vector3(_ballPushDir.x - ballPushOrgin.x, <span style="color: #, <span style="color: #);
pushed = true;
ballTrans.position = new Vector3(hit.point.x, <span style="color: #.558f + ballRadius * <span style="color: #.01f, <span style="color: #.026f);
GetComponent&Rigidbody&().isKinematic = false;
ballTrans.GetComponent&Rigidbody&().AddForce((transform.forward + ballPushDir) * <span style="color: #, ForceMode.Impulse);
<span style="color: #0
<span style="color: #1
<span style="color: #2
<span style="color: #3
<span style="color: #4
<span style="color: #5
<span style="color: #6
/// &summary&
<span style="color: #7
/// 碰撞器检测
<span style="color: #8
/// &/summary&
<span style="color: #9
/// &param name="collision"&&/param&
<span style="color: #0
private void OnCollisionEnter(Collision collision)
<span style="color: #1
<span style="color: #2
if (collision.gameObject.layer != <span style="color: # && pushed)
<span style="color: #3
<span style="color: #4
//Debug.Log("球出界了!");
<span style="color: #5
isOutArea = true;
<span style="color: #6
<span style="color: #7
<span style="color: #8 }
BallController.cs
1 using System.C
2 using System.Collections.G
3 using UnityE
4 /// &summary&
5 /// 保龄球的控制
6 /// &/summary&
7 public class BallController : MonoBehaviour
#region 射线相关
/// &summary&
/// 射线碰撞信息
/// &/summary&
private RaycastH
/// &summary&
/// 图层遮罩
/// &/summary&
private LayerM
/// &summary&
/// 球的位置
/// &/summary&
public Transform ballT
#endregion
/// &summary&
/// 球的半径
/// &/summary&
[SerializeField]
private float ballR
/// &summary&
/// 扔球点
/// &/summary&
private Vector3 ballPushO
/// &summary&
/// 球左右方向差量
/// &/summary&
private Vector3 ballPushD
/// &summary&
/// 是否推出去
/// &/summary&
public bool pushed = false;
/// &summary&
/// 是否撞墙
/// &/summary&
public bool ishitW
/// &summary&
/// 出界了
/// &/summary&
public bool isOutA
/// &summary&
/// 保龄球初始化
/// &/summary&
public void Inits() {
//获取球的半径
ballRadius = ballTrans.GetComponent&SphereCollider&().
GetComponent&Rigidbody&().velocity = Vector3.
GetComponent&Rigidbody&().isKinematic = true;//不受动力
isOutArea = false;//没有越界
pushed = false;//没有推出去
ishitWall =false;//没有撞墙
private void Update()
//发射一条射线
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//如果还没有推出去这个球
if (!pushed)
//推球逻辑
if (Physics.Raycast(ray, out hit, <span style="color: #00, LayerMask.GetMask("AreaFloor")))
Vector3 _ballPushTrans = new Vector3(hit.point.x, <span style="color: #.558f + ballRadius * <span style="color: #.01f, <span style="color: #.026f);
if (hit.transform == GameManage.Instacne.pushArea)
_ballPushTrans = new Vector3(hit.point.x, hit.point.y + <span style="color: #.3f, hit.point.z);//球的位置
ballTrans.position = _ballPushT
ballPushOrgin = hit. ;//记录球的起点
//Debug.Log(hit.point.x + "," + hit.point.y + "," + hit.point.z);
if (!pushed && hit.point.z & 8f && ballPushOrgin != Vector3.zero)//捡起保龄球并且它的发射距离超过世界坐标Z=8f(没有)
Vector3 _ballPushDir = hit.//记录一下球的终点
Debug.Log(ballPushOrgin);
ballPushDir = new Vector3(_ballPushDir.x - ballPushOrgin.x, <span style="color: #, <span style="color: #);
pushed = true;
ballTrans.position = new Vector3(hit.point.x, <span style="color: #.558f + ballRadius * <span style="color: #.01f, <span style="color: #.026f);
GetComponent&Rigidbody&().isKinematic = false;
ballTrans.GetComponent&Rigidbody&().AddForce((transform.forward + ballPushDir) * <span style="color: #, ForceMode.Impulse);
<span style="color: #0
<span style="color: #1
<span style="color: #2
<span style="color: #3
<span style="color: #4
<span style="color: #5
<span style="color: #6
/// &summary&
<span style="color: #7
/// 碰撞器检测
<span style="color: #8
/// &/summary&
<span style="color: #9
/// &param name="collision"&&/param&
<span style="color: #0
private void OnCollisionEnter(Collision collision)
<span style="color: #1
<span style="color: #2
if (collision.gameObject.layer != <span style="color: # && pushed)
<span style="color: #3
<span style="color: #4
//Debug.Log("球出界了!");
<span style="color: #5
isOutArea = true;
<span style="color: #6
<span style="color: #7
<span style="color: #8 }
BallController.cs
打第一轮测试一下效果,额,测试了八九次才打出Strike,非常理想的达到预期了的效果:
8、游戏逻辑实现(多次开局摆放瓶子)
保龄球每打完一局就应该把倒的瓶子清除,然后重新摆放。
&其实摆放瓶子方法也很好分析,每轮结束销毁瓶子堆,不结束就把倒得那些隐藏掉SetActive(false)。
关于何时销毁,我选择把它放在分数统计里调用,因为只有经过分数统计你才知道是否所有瓶子都倒下了。
摆放的方法放在生成新球的后面:
而摆放瓶子的方法如下:
1    /// &summary&
/// 摆放瓶子
/// &/summary&
public void SetBowls()
if (bowls == null)//没有瓶子
bowls = Instantiate(bowlsPrefabs, bowlsParentTrans) as GameO
AllBowls = new Bowl[<span style="color: #];//<span style="color: #个瓶
<span style="color: #
foreach (var item in bowls.GetComponentsInChildren&Bowl&())
<span style="color: #
<span style="color: #
AllBowls[item.Index] =//把加载的瓶子放进数组里
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
foreach (var item in AllBowls)
<span style="color: #
<span style="color: #
if (item.GetScore)//没有倒下过显示他们
<span style="color: #
<span style="color: #
item.gameObject.SetActive(!item.GetScore);
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
&关于对象的绑定:
GameManage.cs里面的代码也越来越多,整理以后的GameManage如下:
1 //------------------------------------------------------------------------------
2 // Copyright 2017 21世纪少年. All rights reserved.
4 // Unity5.6.3f1 Editor make it
5 // BowlingHall_Project
7 // CreatTime: #10/7/2017#
8 // Author: Unity Guo
9 //------------------------------------------------------------------------------
10 using System.C
11 using System.Collections.G
12 using UnityE
13 using UnityEngine.UI;
15 public class GameManage : MonoBehaviour
#region 单例
private static GameManage _I
/// &summary&
/// 游戏管理单例
/// &/summary&
public static GameManage Instacne
private void Awake()
_Instacne = this;
#endregion
#region 场景信息
/// &summary&
/// &/summary&
public Transform roomW
/// &summary&
/// 推力范围
/// &/summary&
public Transform pushA
/// &summary&
/// 保龄球瓶堆的父物体位置
/// &/summary&
public Transform bowlsParentT
#endregion
#region 游戏对象
/// &summary&
/// 保龄球瓶预制体
/// &/summary&
public GameObject bowlsP
/// &summary&
/// 保龄球瓶堆
/// &/summary&
public GameO
/// &summary&
/// 保龄球预制体
/// &/summary&
public GameObject ballP
/// &summary&
/// 保龄球对象
/// &/summary&
public GameO
/// &summary&
/// 保龄球上的控制器
/// &/summary&
public BallController _BallC
#endregion
#region 时间管理
/// &summary&
/// 出界等待时间
/// &/summary&
[SerializeField]
private float outAreaWaitTime = 5f;
private float _
/// &summary&
/// 每球声明时间
/// &/summary&
[SerializeField]
private float BallLifeTime = 30f;
/// &summary&
/// 滚动时间
/// &/summary&
private float _tempL
#endregion
<span style="color: #0
/// &summary&
<span style="color: #1
/// 每局分数块游戏对象
<span style="color: #2
/// &/summary&
<span style="color: #3
public ScoreItem[] SocreI
<span style="color: #4
/// &summary&
<span style="color: #5
/// 管理所有瓶子的数组
<span style="color: #6
/// &/summary&
<span style="color: #7
public Bowl[] AllB
<span style="color: #8
/// &summary&
<span style="color: #9
/// 每球的临时得分
<span style="color: #0
/// &/summary&
<span style="color: #1
public int _tempS
<span style="color: #2
/// &summary&
<span style="color: #3
<span style="color: #4
/// &/summary&
<span style="color: #5
public int indexI
<span style="color: #6
/// &summary&
<span style="color: #7
/// 每轮第N球
<span style="color: #8
/// &/summary&
<span style="color: #9
public int _tempNumB
<span style="color: #0
<span style="color: #1
private void Start()
<span style="color: #2
<span style="color: #3
indexItem = <span style="color: #;
<span style="color: #4
_tempNumBall = <span style="color: #;//第1球
<span style="color: #5
SetBall();
<span style="color: #6
SetBowls();
<span style="color: #7
<span style="color: #8
private void Update()
<span style="color: #9
<span style="color: #0
if (ball != null)
<span style="color: #1
<span style="color: #2
if (_BallController.pushed)//球已经被推出去
<span style="color: #3
<span style="color: #4
_tempLife += Time.deltaT
<span style="color: #5
if (_tempLife & BallLifeTime && !_BallController.isOutArea)//一直没出届
<span style="color: #6
<span style="color: #7
Debug.Log("此球分数:" + _tempScore);
<span style="color: #8
SetScore(_tempScore);
<span style="color: #9
_tempLife = <span style="color: #;
<span style="color: #0
_tempScore = <span style="color: #;//清零
<span style="color: #1
DestroyImmediate(ball);
<span style="color: #2
SetBall();
<span style="color: #3
SetBowls();
<span style="color: #4
<span style="color: #5
if (_BallController.isOutArea)//球出界
<span style="color: #6
<span style="color: #7
_temp += Time.deltaT
<span style="color: #8
if (_temp & outAreaWaitTime)//超过出界时间
<span style="color: #9
<span style="color: #0
Debug.Log("球出界!此球得分:" + _tempScore);
<span style="color: #1
SetScore(_tempScore);
<span style="color: #2
_tempLife = <span style="color: #;
<span style="color: #3
_temp = <span style="color: #;//重新计时
<span style="color: #4
_tempScore = <span style="color: #;//清零
<span style="color: #5
DestroyImmediate(ball);
<span style="color: #6
SetBall();
<span style="color: #7
SetBowls();
<span style="color: #8
<span style="color: #9
<span style="color: #0
<span style="color: #1
<span style="color: #2
<span style="color: #3
/// &summary&
<span style="color: #4
/// 生成新球
<span style="color: #5
/// &/summary&
<span style="color: #6
public void SetBall()
<span style="color: #7
<span style="color: #8
if (ball == null)
<span style="color: #9
<span style="color: #0
ball = Instantiate(ballPrefab) as GameO
<span style="color: #1
_BallController = ball.GetComponent&BallController&();
<span style="color: #2
_BallController.Inits();
<span style="color: #3
<span style="color: #4
<span style="color: #5
/// &summary&
<span style="color: #6
/// 传递分数
<span style="color: #7
/// &/summary&
<span style="color: #8
/// &param name="_score"&分数值&/param&
<span style="color: #9
public void SetScore(int _score)
<span style="color: #0
<span style="color: #1
//indexItem++;//轮数自加,(indexItem-1)为每局分数块游戏对象SocreItems索引
<span style="color: #2
if (indexItem & <span style="color: #)//前九轮
<span style="color: #3
<span style="color: #4
if (_tempNumBall == <span style="color: #)//第一球
<span style="color: #5
<span style="color: #6
SocreItems[indexItem].SetScoreText(<span style="color: #, _score);//设置第一球
<span style="color: #7
SocreItems[indexItem].ShowScore();
<span style="color: #8
if (_score == <span style="color: #)//分数为10
<span style="color: #9
<span style="color: #0
Debug.LogWarning("Strike全中!");
<span style="color: #1
SocreItems[indexItem].isStrike = true;//设置第一球
<span style="color: #2
indexItem++;//轮数自加,(indexItem-1)为每局分数块游戏对象SocreItems索引
<span style="color: #3
DestroyImmediate(bowls);//清空瓶子
<span style="color: #4
_tempNumBall = <span style="color: #;//开始新的一轮
<span style="color: #5
<span style="color: #6
else//不为10
<span style="color: #7
<span style="color: #8
_tempNumBall = <span style="color: #;//开始下一个球
<span style="color: #9
<span style="color: #0
<span style="color: #1
else if (_tempNumBall == <span style="color: #)//第二球
<span style="color: #2
<span style="color: #3
SocreItems[indexItem].SetScoreText(<span style="color: #, _score);//设置第一球
<span style="color: #4
SocreItems[indexItem].ShowScore();
<span style="color: #5
if (_score + SocreItems[indexItem].Scores[<span style="color: #] == <span style="color: #)//yi
<span style="color: #6
<span style="color: #7
Debug.LogWarning("Spare补中!");
<span style="color: #8
SocreItems[indexItem].isSpare = true;//设置第一球
<span style="color: #9
<span style="color: #0
indexItem++;//轮数自加,(indexItem-1)为每局分数块游戏对象SocreItems索引
<span style="color: #1
DestroyImmediate(bowls);//清空瓶子
<span style="color: #2
_tempNumBall = <span style="color: #;//开始新的一轮
<span style="color: #3
<span style="color: #4
<span style="color: #5
<span style="color: #6
<span style="color: #7
/// &summary&
<span style="color: #8
/// 摆放瓶子
<span style="color: #9
/// &/summary&
<span style="color: #0
public void SetBowls()
<span style="color: #1
<span style="color: #2
if (bowls == null)//没有瓶子
<span style="color: #3
<span style="color: #4
bowls = Instantiate(bowlsPrefabs, bowlsParentTrans) as GameO
<span style="color: #5
AllBowls = new Bowl[<span style="color: #];//<span style="color: #个瓶
<span style="color: #6
foreach (var item in bowls.GetComponentsInChildren&Bowl&())
<span style="color: #7
<span style="color: #8
AllBowls[item.Index] =//把加载的瓶子放进数组里
<span style="color: #9
<span style="color: #0
<span style="color: #1
<span style="color: #2
<span style="color: #3
foreach (var item in AllBowls)
<span style="color: #4
<span style="color: #5
if (item.GetScore)//没有倒下过显示他们
<span style="color: #6
<span style="color: #7
item.gameObject.SetActive(!item.GetScore);
<span style="color: #8
<span style="color: #9
<span style="color: #0
<span style="color: #1
<span style="color: #2 }
GameManage
&9、游戏逻辑实现(Strike全中和Spare补中计分实现)
好了到最麻烦的地方了,分数逻辑设置重新理清一下得分思路,在前面我们写了一个SetSocre()方法设置分数,但是没法处理补分和全中,而且也没有办法处理第十轮,所以我们稍加修改,完善并添加特殊加分方法AddScore(),在ScoreItem类中,每次设置分数都让他重新设置特殊分数:
而且之前分数我们直接用int[]的数组存储,我们改进一下在,ScoreItem中添加一个特殊类Score:
1 /// &summary&
2 /// 分数信息类
3 /// &/summary&
4 public class Score
/// &summary&
/// Score构造参数
/// &/summary&
/// &param name="_value"&&/param&
<span style="color: #
public Score(int _value)
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
/// &summary&
<span style="color: #
/// 分数值
<span style="color: #
/// &/summary&
<span style="color: #
private int
<span style="color: #
/// &summary&
<span style="color: #
/// 获取分数值
<span style="color: #
/// &/summary&
<span style="color: #
public int Value
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: # }
当有分数时实例化一个Score,构造传值分数赋值,而且这个分数不可修改,封装起来只能获取,保证了外界不能修改你的分数。
理清思路逻辑,接下来进行编码:
1 using System.C
2 using System.Collections.G
3 using UnityE
4 using UnityEngine.UI;
6 /// &summary&
7 /// 分数信息类
8 /// &/summary&
9 public class Score
/// &summary&
/// Score构造参数
/// &/summary&
/// &param name="_value"&&/param&
public Score(int _value)
/// &summary&
/// 分数值
/// &/summary&
private int
/// &summary&
/// 获取分数值
/// &/summary&
public int Value
34 public class ScoreItem : MonoBehaviour
/// &summary&
/// &/summary&
public int
/// &summary&
/// 所有分数文字
/// &/summary&
public Text[] SocreT
/// &summary&
/// 每轮分数
/// &/summary&
public Score[] S
/// &summary&
/// 本轮分数临时总和
/// &/summary&
public int _tempScoreI
/// &summary&
/// 本轮分数总和
/// &/summary&
public int _S
/// &summary&
/// 本轮全中?
/// &/summary&
public bool isStrike = false;
/// &summary&
/// 本轮补中?
/// &/summary&
public bool isSpare = false;
/// &summary&
/// 初始化
/// &/summary&
public void Inits()
Scores = new Score[SocreTexts.Length - <span style="color: #];//每轮分数初始化
/// &summary&
/// 每轮分数设置索引为_index的分数文本的值为_score
/// &/summary&
/// &param name="_index"&索引&/param&
/// &param name="_score"&分数&/param&
public void SetScoreText(int _index, int _score)
Scores[_index] = new Score(_score);
Debug.LogWarning("第"+index+"轮:"+_index+"球:分数"+_score);
_tempScoreItem = <span style="color: #;
foreach (var item in Scores)
if (item != null)
_tempScoreItem += item.V//累加本轮分数总和
/// &summary&
/// 显示所有分数
/// &/summary&
public void ShowScore()
//设置每轮
for (int i = <span style="color: #; i & SocreTexts.Length - <span style="color: #; i++)
if (Scores[i] != null)
SocreTexts[i].text = Scores[i].Value.ToString();
<span style="color: #0
<span style="color: #1
<span style="color: #2
<span style="color: #3
SocreTexts[i].text = "";
<span style="color: #4
<span style="color: #5
<span style="color: #6
//AddScore();
<span style="color: #7
<span style="color: #8
/// &summary&
<span style="color: #9
/// 更新添加分数
<span style="color: #0
/// &/summary&
<span style="color: #1
public void AddScore()
<span style="color: #2
<span style="color: #3
_Score = _tempScoreI//分数
<span style="color: #4
int _tempTime = <span style="color: #;//临时次数计数
<span style="color: #5
if (isStrike)//全中
<span style="color: #6
<span style="color: #7
if (index & <span style="color: #)//当前是前九个分数块
<span style="color: #8
<span style="color: #9
foreach (var item in GameManage.Instacne.SocreItems[index + <span style="color: #].Scores)//遍历下一轮所有分数
<span style="color: #0
<span style="color: #1
if (item != null)//不为空加分
<span style="color: #2
<span style="color: #3
_Score += item.V//分数
<span style="color: #4
_tempTime++;
<span style="color: #5
if (_tempTime == <span style="color: #)
<span style="color: #6
<span style="color: #7
<span style="color: #8
<span style="color: #9
<span style="color: #0
<span style="color: #1
<span style="color: #2
if (index &<span style="color: #)//前八个
<span style="color: #3
<span style="color: #4
if (GameManage.Instacne.SocreItems[index + <span style="color: #].Scores[<span style="color: #] != null)//下一个球也是补中的情况
<span style="color: #5
<span style="color: #6
_Score += GameManage.Instacne.SocreItems[index + <span style="color: #].Scores[<span style="color: #].V
<span style="color: #7
_tempTime++;
<span style="color: #8
<span style="color: #9
<span style="color: #0
<span style="color: #1
<span style="color: #2
<span style="color: #3
<span style="color: #4
<span style="color: #5
if (isSpare)
<span style="color: #6
<span style="color: #7
if (index &<span style="color: #)//前八个
<span style="color: #8
<span style="color: #9
if (GameManage.Instacne.SocreItems[index + <span style="color: #].Scores[<span style="color: #] != null)
<span style="color: #0
<span style="color: #1
_Score += GameManage.Instacne.SocreItems[index + <span style="color: #].Scores[<span style="color: #].V
<span style="color: #2
_tempTime++;//一次
<span style="color: #3
<span style="color: #4
<span style="color: #5
else if(index ==<span style="color: #)//第九个
<span style="color: #6
<span style="color: #7
<span style="color: #8
<span style="color: #9
SocreTexts[SocreTexts.Length - <span style="color: #].text = _Score.ToString();//总分设置
<span style="color: #0
<span style="color: #1 }
ScoreItem.cs
&对了再加一个IsOver,游戏结束设置为True,修改之后的GameManage:
1 using System.C
2 using System.Collections.G
3 using UnityE
4 using UnityEngine.UI;
6 public class GameManage : MonoBehaviour
#region 单例
private static GameManage _I
/// &summary&
/// 游戏管理单例
/// &/summary&
public static GameManage Instacne
private void Awake()
_Instacne = this;
#endregion
#region 场景信息
/// &summary&
/// &/summary&
public Transform roomW
/// &summary&
/// 推力范围
/// &/summary&
public Transform pushA
/// &summary&
/// 保龄球瓶堆的父物体位置
/// &/summary&
public Transform bowlsParentT
#endregion
#region 游戏对象
/// &summary&
/// 保龄球瓶预制体
/// &/summary&
public GameObject bowlsP
/// &summary&
/// 保龄球瓶堆
/// &/summary&
public GameO
/// &summary&
/// 保龄球预制体
/// &/summary&
public GameObject ballP
/// &summary&
/// 保龄球对象
/// &/summary&
public GameO
/// &summary&
/// 保龄球上的控制器
/// &/summary&
public BallController _BallC
/// &summary&
/// 管理所有瓶子的数组
/// &/summary&
public Bowl[] AllB
#endregion
#region 时间管理
/// &summary&
/// 出界等待时间
/// &/summary&
[SerializeField]
private float outAreaWaitTime = 5f;
private float _
/// &summary&
/// 每球声明时间
/// &/summary&
[SerializeField]
private float BallLifeTime = 30f;
/// &summary&
/// 滚动时间
/// &/summary&
private float _tempL
#endregion
#region 分数管理
/// &summary&
/// 每局分数块游戏对象
/// &/summary&
<span style="color: #0
public ScoreItem[] SocreI
<span style="color: #1
/// &summary&
<span style="color: #2
/// 每球的临时得分
<span style="color: #3
/// &/summary&
<span style="color: #4
public int _tempS
<span style="color: #5
/// &summary&
<span style="color: #6
/// 所有总分
<span style="color: #7
/// &/summary&
<span style="color: #8
public int AllS
<span style="color: #9
/// &summary&
<span style="color: #0
/// 所有分数
<span style="color: #1
/// &/summary&
<span style="color: #2
public Text AllScoreT
<span style="color: #3
#endregion
<span style="color: #4
/// &summary&
<span style="color: #5
<span style="color: #6
/// &/summary&
<span style="color: #7
public int indexI
<span style="color: #8
/// &summary&
<span style="color: #9
/// 每轮第N球
<span style="color: #0
/// &/summary&
<span style="color: #1
public int _tempNumB
<span style="color: #2
/// &summary&
<span style="color: #3
/// 游戏结束
<span style="color: #4
/// &/summary&
<span style="color: #5
public bool IsO
<span style="color: #6
<span style="color: #7
private void Start()
<span style="color: #8
<span style="color: #9
indexItem = <span style="color: #;
<span style="color: #0
_tempNumBall = <span style="color: #;//第1球
<span style="color: #1
SetBall();
<span style="color: #2
SetBowls();
<span style="color: #3
//分数初始化
<span style="color: #4
foreach (var item in SocreItems)
<span style="color: #5
<span style="color: #6
item.Inits();//初始化
<span style="color: #7
item.ShowScore();
<span style="color: #8
<span style="color: #9
<span style="color: #0
private void Update()
<span style="color: #1
<span style="color: #2
if (ball != null)//游戏没有结束
<span style="color: #3
<span style="color: #4
<span style="color: #5
if (_BallController.pushed)//球已经被推出去
<span style="color: #6
<span style="color: #7
_tempLife += Time.deltaT
<span style="color: #8
if (_tempLife & BallLifeTime && !_BallController.isOutArea)//一直没出届
<span style="color: #9
<span style="color: #0
Debug.Log("此球分数:" + _tempScore);
<span style="color: #1
_tempLife = <span style="color: #;
<span style="color: #2
DestroyImmediate(ball);
<span style="color: #3
SetScore(_tempScore);
<span style="color: #4
_tempScore = <span style="color: #;//清零
<span style="color: #5
SetBall();
<span style="color: #6
SetBowls();
<span style="color: #7
<span style="color: #8
if (_BallController.isOutArea)//球出界
<span style="color: #9
<span style="color: #0
_temp += Time.deltaT
<span style="color: #1
if (_temp & outAreaWaitTime)//超过出界时间
<span style="color: #2
<span style="color: #3
Debug.Log("球出界!此球得分:" + _tempScore);
<span style="color: #4
_tempLife = <span style="color: #;
<span style="color: #5
_temp = <span style="color: #;//重新计时
<span style="color: #6
DestroyImmediate(ball);
<span style="color: #7
SetScore(_tempScore);
<span style="color: #8
_tempScore = <span style="color: #;//清零
<span style="color: #9
SetBall();
<span style="color: #0
SetBowls();
<span style="color: #1
<span style="color: #2
<span style="color: #3
<span style="color: #4
<span style="color: #5
<span style="color: #6
<span style="color: #7
<span style="color: #8
/// &summary&
<span style="color: #9
/// 生成新球
<span style="color: #0
/// &/summary&
<span style="color: #1
public void SetBall()
<span style="color: #2
<span style="color: #3
if (ball == null)
<span style="color: #4
<span style="color: #5
ball = Instantiate(ballPrefab) as GameO
<span style="color: #6
_BallController = ball.GetComponent&BallController&();
<span style="color: #7
_BallController.Inits();
<span style="color: #8
<span style="color: #9
<span style="color: #0
/// &summary&
<span style="color: #1
/// 传递分数
<span style="color: #2
/// &/summary&
<span style="color: #3
/// &param name="_score"&分数值&/param&
<span style="color: #4
public void SetScore(int _score)
<span style="color: #5
<span style="color: #6
//indexItem++;//轮数自加,(indexItem-1)为每局分数块游戏对象SocreItems索引
<span style="color: #7
if (indexItem & <span style="color: #)//---------------------------------------------------前九轮
<span style="color: #8
<span style="color: #9
if (_tempNumBall == <span style="color: #)//第一球
<span style="color: #0
<span style="color: #1
SocreItems[indexItem].SetScoreText(<span style="color: #, _score);//设置第一球
<span style="color: #2
SocreItems[indexItem].ShowScore();
<span style="color: #3
if (_score == <span style="color: #)//分数为10
<span style="color: #4
<span style="color: #5
Debug.LogWarning("Strike全中!");
<span style="color: #6
SocreItems[indexItem].isStrike = true;//设置第一球
<span style="color: #7
indexItem++;//轮数自加,(indexItem-1)为每局分数块游戏对象SocreItems索引
<span style="color: #8
DestroyImmediate(bowls);//清空瓶子
<span style="color: #9
_tempNumBall = <span style="color: #;//开始新的一轮
<span style="color: #0
<span style="color: #1
else//不为10
<span style="color: #2
<span style="color: #3
_tempNumBall = <span style="color: #;//开始下一个球
<span style="color: #4
<span style="color: #5
<span style="color: #6
else if (_tempNumBall == <span style="color: #)//第二球
<span style="color: #7
<span style="color: #8
SocreItems[indexItem].SetScoreText(<span style="color: #, _score);//设置第一球
<span style="color: #9
SocreItems[indexItem].ShowScore();
<span style="color: #0
if (_score + SocreItems[indexItem].Scores[<span style="color: #].Value == <span style="color: #)//yi
<span style="color: #1
<span style="color: #2
Debug.LogWarning("Spare补中!");
<span style="color: #3
SocreItems[indexItem].isSpare = true;//设置第一球
<span style="color: #4
<span style="color: #5
indexItem++;//轮数自加,(indexItem-1)为每局分数块游戏对象SocreItems索引
<span style="color: #6
DestroyImmediate(bowls);//清空瓶子
<span style="color: #7
_tempNumBall = <span style="color: #;//开始新的一轮
<span style="color: #8
<span style="color: #9
<span style="color: #0
<span style="color: #1
else if (indexItem == <span style="color: #)//--------------------------------------------第十轮
<span style="color: #2
<span style="color: #3
if (_tempNumBall == <span style="color: #)//第一球
<span style="color: #4
<span style="color: #5
if (_score == <span style="color: #)
<span style="color: #6
<span style="color: #7
Debug.LogWarning("Strike全中!");
<span style="color: #8
SocreItems[indexItem].isStrike = true;//设置第一球
<span style="color: #9
DestroyImmediate(bowls);//清空瓶子
<span style="color: #0
<span style="color: #1
SocreItems[indexItem].SetScoreText(_tempNumBall - <span style="color: #, _score);//设置第一球
<span style="color: #2
SocreItems[indexItem].ShowScore();
<span style="color: #3
_tempNumBall = <span style="color: #;//开始新的一轮
<span style="color: #4
<span style="color: #5
else if (_tempNumBall == <span style="color: #)//第二球
<span style="color: #6
<span style="color: #7
if (!SocreItems[indexItem].isStrike)//不是全中
<span style="color: #8
<span style="color: #9
if (SocreItems[indexItem].Scores[<span style="color: #].Value + _score == <span style="color: #)//达成补中条件
<span style="color: #0
<span style="color: #1
Debug.LogWarning("Spare补中!");
<span style="color: #2
SocreItems[indexItem].isSpare = true;//全中
<span style="color: #3
DestroyImmediate(bowls);//清空瓶子
<span style="color: #4
SocreItems[indexItem].SetScoreText(_tempNumBall - <span style="color: #, _score);//设置第二球分数
<span style="color: #5
SocreItems[indexItem].ShowScore();
<span style="color: #6
_tempNumBall = <span style="color: #;//开始新的一轮,第3球
<span style="color: #7
<span style="color: #8
<span style="color: #9
<span style="color: #0
SocreItems[indexItem].SetScoreText(_tempNumBall - <span style="color: #, _score);//设置第二球分数
<span style="color: #1
SocreItems[indexItem].ShowScore();
<span style="color: #2
IsOver = true;
<span style="color: #3
<span style="color: #4
<span style="color: #5
else//全中下一球
<span style="color: #6
<span style="color: #7
DestroyImmediate(bowls);//清空瓶子
<span style="color: #8
SocreItems[<span style="color: #].SetScoreText(_tempNumBall - <span style="color: #, _score);//设置第二球分数
<span style="color: #9
SocreItems[<span style="color: #].ShowScore();
<span style="color: #0
_tempNumBall = <span style="color: #;//开始新的一轮,第3球
<span style="color: #1
<span style="color: #2
<span style="color: #3
else if (_tempNumBall == <span style="color: #)
<span style="color: #4
<span style="color: #5
DestroyImmediate(bowls);//清空瓶子
<span style="color: #6
SocreItems[indexItem].SetScoreText(_tempNumBall - <span style="color: #, _score);//设置第一球分数
<span style="color: #7
SocreItems[indexItem].ShowScore();
<span style="color: #8
<span style="color: #9
IsOver = true;
<span style="color: #0
<span style="color: #1
<span style="color: #2
AllScore = <span style="color: #;
<span style="color: #3
foreach (var item in SocreItems)//加分
<span style="color: #4
<span style="color: #5
item.AddScore();
<span style="color: #6
AllScore += item._S
<span style="color: #7
<span style="color: #8
AllScoreText.text = AllScore.ToString();
<span style="color: #9
<span style="color: #0
<span style="color: #1
/// &summary&
<span style="color: #2
/// 摆放瓶子
<span style="color: #3
/// &/summary&
<span style="color: #4
public void SetBowls()
<span style="color: #5
<span style="color: #6
if (bowls == null)//没有瓶子
<span style="color: #7
<span style="color: #8
bowls = Instantiate(bowlsPrefabs, bowlsParentTrans) as GameO
<span style="color: #9
AllBowls = new Bowl[<span style="color: #];//<span style="color: #个瓶
<span style="color: #0
foreach (var item in bowls.GetComponentsInChildren&Bowl&())
<span style="color: #1
<span style="color: #2
AllBowls[item.Index] =//把加载的瓶子放进数组里
<span style="color: #3
<span style="color: #4
<span style="color: #5
<span style="color: #6
<span style="color: #7
foreach (var item in AllBowls)
<span style="color: #8
<span style="color: #9
if (item.GetScore)//没有倒下过显示他们
<span style="color: #0
<span style="color: #1
item.gameObject.SetActive(!item.GetScore);
<span style="color: #2
<span style="color: #3
<span style="color: #4
<span style="color: #5
<span style="color: #6 }
GameManage.cs
此外修改一下BallController.cs:
这样游戏结束就捡不起来球了。
&到目前测试一下,基本上游戏大体逻辑已完全解决!但是这并不是最终代码,得分和现实已经没有问题:
&10、开始界面的搭建
&和Main场景搭建手法差不多,搭建一个Start场景。
接下来然后搭建Start的UI界面,我们发现这个按钮素材需要九宫切图,于是切一下:
经过一系列的UI布局:
关于场景的替换需要注意一下,不要用Application.loadedLevel(),导入UnityEngine.SceneManagement包,用SceneManager.LoadScene():
我们再编写一个游戏管理的脚本StartManage.cs,让它负责场景的切换和球的表面材质替换。
1 using System.C
2 using System.Collections.G
3 using UnityE
4 using UnityEngine.SceneM
5 using UnityEngine.UI;
7 public class StartManage : MonoBehaviour
/// &summary&
<span style="color: #
/// 开始按键
<span style="color: #
/// &/summary&
<span style="color: #
public Button PlayB
<span style="color: #
/// &summary&
<span style="color: #
/// 上一个球
<span style="color: #
/// &/summary&
<span style="color: #
public Button PrevB
<span style="color: #
/// &summary&
<span style="color: #
/// 下一个球
<span style="color: #
/// &/summary&
<span style="color: #
public Button NextB
<span style="color: #
/// &summary&
<span style="color: #
/// 球的材质列表
<span style="color: #
/// &/summary&
<span style="color: #
[SerializeField]
<span style="color: #
private Texture[] ballT
<span style="color: #
/// &summary&
<span style="color: #
/// 当前材质索引
<span style="color: #
/// &/summary&
<span style="color: #
[SerializeField]
<span style="color: #
private int _tempI
<span style="color: #
/// &summary&
<span style="color: #
/// 球的材质贴图
<span style="color: #
/// &/summary&
<span style="color: #
public Material ballM
<span style="color: #
<span style="color: #
void Start()
<span style="color: #
<span style="color: #
_tempIndex = <span style="color: #;
<span style="color: #
PlayBtn.onClick.AddListener(playBtnClick);
<span style="color: #
PrevBtn.onClick.AddListener(UpdateRevTexture);
<span style="color: #
NextBtn.onClick.AddListener(UpdateNextTexture);
<span style="color: #
<span style="color: #
public void playBtnClick()
<span style="color: #
<span style="color: #
SceneManager.LoadScene("Main");
<span style="color: #
<span style="color: #
/// &summary&
<span style="color: #
/// 更换上一个材质
<span style="color: #
/// &/summary&
<span style="color: #
public void UpdateRevTexture() {
<span style="color: #
_tempIndex--;
<span style="color: #
if (_tempIndex==-<span style="color: #)
<span style="color: #
<span style="color: #
_tempIndex = ballTextures.Length - <span style="color: #;
<span style="color: #
<span style="color: #
ballMaterial.SetTexture("_MainTex", ballTextures[_tempIndex]);
<span style="color: #
<span style="color: #
/// &summary&
<span style="color: #
/// 更换下一个材质
<span style="color: #
/// &/summary&
<span style="color: #
public void UpdateNextTexture()
<span style="color: #
<span style="color: #
_tempIndex++;
<span style="color: #
if (_tempIndex == ballTextures.Length)
<span style="color: #
<span style="color: #
_tempIndex = <span style="color: #;
<span style="color: #
<span style="color: #
ballMaterial.SetTexture("_MainTex", ballTextures[_tempIndex]);
<span style="color: #
<span style="color: # }
StartManage.cs
&绑定一下:
这样还没有完。我们还需要一个步骤,从游戏界面返回初始界面。打开Main场景,制作一个返回按键。
经过测试后,完成之后两个场景完美切换。
11、发球后的相机跟随
&在GameManage上声明主相机Transform变量,绑定
在BallController添加以下代码:
相机跟随实现。
修改后的BallController代码:
1 using System.C
2 using System.Collections.G
3 using UnityE
4 /// &summary&
5 /// 保龄球的控制
6 /// &/summary&
7 public class BallController : MonoBehaviour
#region 射线相关
/// &summary&
/// 射线碰撞信息
/// &/summary&
private RaycastH
/// &summary&
/// 图层遮罩
/// &/summary&
private LayerM
/// &summary&
/// 球的位置
/// &/summary&
public Transform ballT
#endregion
/// &summary&
/// 球的半径
/// &/summary&
[SerializeField]
private float ballR
/// &summary&
/// 扔球点
/// &/summary&
private Vector3 ballPushO
/// &summary&
/// 球左右方向差量
/// &/summary&
private Vector3 ballPushD
/// &summary&
/// 是否推出去
/// &/summary&
public bool pushed = false;
/// &summary&
/// 是否撞墙
/// &/summary&
public bool ishitW
/// &summary&
/// 出界了
/// &/summary&
public bool isOutA
/// &summary&
/// 与相机差距位置
/// &/summary&
private Vector3 _tempP
/// &summary&
/// 保龄球初始化
/// &/summary&
public void Inits()
//获取球的半径
ballRadius = ballTrans.GetComponent&SphereCollider&().
GetComponent&Rigidbody&().velocity = Vector3.
GetComponent&Rigidbody&().isKinematic = true;//不受动力
isOutArea = false;//没有越界
pushed = false;//没有推出去
ishitWall = false;//没有撞墙
GameManage.Instacne.CameraTrans.localPosition = Vector3.
_tempPos = new Vector3(<span style="color: #, -<span style="color: #.5f, -<span style="color: #);
private void Update()
//发射一条射线
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//如果还没有推出去这个球
if (!pushed && !GameManage.Instacne.IsOver)
//推球逻辑
if (Physics.Raycast(ray, out hit, <span style="color: #00, LayerMask.GetMask("AreaFloor")))
Vector3 _ballPushTrans = new Vector3(hit.point.x, <span style="color: #.558f + ballRadius * <span style="color: #.01f, <span style="color: #.026f);
if (hit.transform == GameManage.Instacne.pushArea)
_ballPushTrans = new Vector3(hit.point.x, hit.point.y + <span style="color: #.3f, hit.point.z);//球的位置
ballTrans.position = _ballPushT
ballPushOrgin = hit. ;//记录球的起点
//Debug.Log(hit.point.x + "," + hit.point.y + "," + hit.point.z);
if (!pushed && hit.point.z & 8f && ballPushOrgin != Vector3.zero)//捡起保龄球并且它的发射距离超过世界坐标Z=8f(没有)
<span style="color: #0
Vector3 _ballPushDir = hit.//记录一下球的终点
<span style="color: #1
//Debug.Log(ballPushOrgin);
<span style="color: #2
ballPushDir = new Vector3(_ballPushDir.x - ballPushOrgin.x, <span style="color: #, <span style="color: #);
<span style="color: #3
pushed = true;
<span style="color: #4
ballTrans.position = new Vector3(hit.point.x, <span style="color: #.558f + ballRadius * <span style

我要回帖

更多关于 unity3d和虚幻4哪个好 的文章

 

随机推荐