这磨人的小游戏项目也要接近尾声了,大概还差一两天的进度吧。最近在看佐佐木智广的《游戏剧本怎么写》,讲了很多Galgame的剧情、脚本设置,非常有意思的一本书,有时间我开个新坑来做一些读书笔记。下一个项目我也打算完成我以前能力不足未能写完的galgame框架,然后交给会剧本会画画的有缘人来操作(>A<),至于新课学习部分,明天离散数学书就来了,准备重点看预备知识巩固和图论部分,后面就做些题吧,暑假也就这样了。不多BB,继续撸项目


本日目标:

1.实现其他障碍物的触发检测
2.重写HeroControler,优化人物的动作

一.其他障碍物的设置

单单把障碍物放在那里让玩家去碰还是有点LOW了,我们加些脚本让障碍物有些变化,然后再加入昨天的动态道具创建,实现场景物体完全的动态生成。

(一)障碍物刺的制作

首先导入一个刺的模型,设置好比例尺,缩放到合适大小。我们来实现这样一个触发器常见效果:主人公走到刺的前面一段距离时,给刺发送信号,让其向玩家移动。还有不同方向的,也都来实现一遍。

这里的做法是使用AddComponent方法来动态添加脚本。先在刺的前面合适距离建一个空对象,作为一个触发装置,添加一个BoxCollider(IsTrigger打勾)。创建一个DynamicAddScript脚本,用于触发检测并给刺添加脚本,再创建一个控制物体移动的脚本ObjMovement。
DynamicAddScript脚本内容:

public class DynamicAddScripts : MonoBehaviour {public GameObject GoNeedObject;//定义添加脚本的对象// Use this for initializationvoid Start () {}private void OnTriggerEnter(Collider col){if(GoNeedObject)//string.isnullorempty{GoNeedObject.AddComponent<MovingObj>();}}// Update is called once per framevoid Update () {}}

ObjMovement脚本写一个简单的移动代码就能看到效果了

this.transform.Translate(Vector3.back * FloMovingSpeed,Space.World);

再来写一个垂直上下移动的刺,添加触发检测和脚本的方法一样,来写一下上下移动的逻辑。需要事先Debug找到合适的最高点和最低点,设为变量。再定义一个正向移动的标志,乘在vector3的后面(控制移动的方向)。

if(this.transform.position.y>FloYPositionmax){UpMovingFlag = -1;}else if(this.transform.position.y<FloYPositionmin){UpMovingFlag = 1;}this.transform.Translate(new Vector3(0,1,0) * MovingSpeed*UpMovingFlag,Space.World);

然后把之前那个碰撞检测结束游戏的脚本绑在对应的刺上。将做好的物体设为预制体,方便之后的动态生成。注意脚本组件挂上相应的GameObject

(二)对障碍物树干的改动

来实现一个触发器控制树从空中落下来的效果,增加游戏难度。方法与之前的大同小异,只不过这回Add的是RigidBody组件。同样,写一个触发器上的脚本TriggerFalling:

public class DynamicTriggerFalling : MonoBehaviour {public GameObject FallingObject;// Use this for initialization
void Start () {}
private void OnTriggerEnter(Collider col){FallingObject.AddComponent<ObjectFalling>();}// Update is called once per framevoid Update () {}

然后是添加刚体组件的脚本主要代码,注意初始化一下刚体的一些属性,用到了GetComponent方法:

private Rigidbody rb1;// Use this for initializationvoid Start () {this.gameObject.AddComponent<Rigidbody>();rb1 = this.gameObject.GetComponent<Rigidbody>();rb1.mass = 5;rb1.useGravity = true;}



障碍物的设置就到这里,之后可以再增加一些特性,接下来来处理角色的动画。

二.角色动作的优化

目前角色的动画都放在HeroController中的,完全由Animation.play()来播放,这样子在加上跳跃,滑铲等动作后会出很大的问题,按下按键后动作会直接切换(不管播没播放结束),十分生硬。为了解决这个问题,需要重新写一下Controller中的内容,使用协程来控制人物动作。当然,这里也可以用动画状态机(animator)来实现,以后有时间专门来复习一下。
首先,在GlobalManager中新加入一个枚举变量,来指示人物的动作

public enum HeroActionType {None,Run,Jump,Bend,Fall}
//initialize
//7.28 action types
public static HeroActionType ActionType = HeroActionType.None;

然后打开HeroController脚本,把之前写的控制角色左右移动以及动画播放的代码全部注释掉,添加两个协程,一个用来接收用户输入,控制角色移动,一个用来控制对应的动作。这里跳跃动作用到了RigidBody的AddForce给物体添加一个冲力的方法来实现。

IEnumerator GetHeroActionInput(){yield return new WaitForEndOfFrame();while(true){yield return new WaitForSeconds(0.01f);if(GlobalManager.GlobalState==GameState.Playing){//Default setting:runningGlobalManager.ActionType = HeroActionType.Run;//Turningif(Input.GetKey(KeyCode.A)){this.transform.Rotate(Vector3.down * FloRotateSpeed);}else if (Input.GetKey(KeyCode.D)){this.transform.Rotate(Vector3.up * FloRotateSpeed);}//Jumpingelse if(Input.GetKeyDown(KeyCode.Space)){HeroRB.AddForce(Vector3.up * HeroJumpPower, ForceMode.Impulse);GlobalManager.ActionType = HeroActionType.Jump;yield return new WaitForSeconds(AmimeJump.length);}else if(Input.GetKeyDown(KeyCode.S)){}}}}IEnumerator PlayHeroAnimation(){yield return new WaitForEndOfFrame();while(true){yield return new WaitForSeconds(0.01f);if (GlobalManager.GlobalState==GameState.Playing){switch(GlobalManager.ActionType){case HeroActionType.None:break;case HeroActionType.Run:anime.Play(AnimeRun.name);yield return new WaitForSeconds(AnimeRun.length);break;case HeroActionType.Jump:anime.Play(AmimeJump.name);yield return new WaitForSeconds(AmimeJump.length);break;case HeroActionType.Bend:break;case HeroActionType.Fall:break;}}}}

最好还是用switch来处理枚举变量。这里我们用到了AnimationClip,即剪辑得来的动画片段,我们把它的时间长度length来作为yield return的秒数,这样就不会出现一个动作还没有做完就强行开始进行下一个动作了。注意定义好animationClip,并且在脚本组件绑上对象。

GlobalManager和HeroController脚本变动很大,这里粘贴一下:
GlobalManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;//enum description:
//none:no sounds
//halfvolume:halfvolume
//fullvolume:fullvolume
public enum ProjectVolume { none,FullVolume,HalfVolume,NoneVolume}//enunm description:
//none:wait for a state
//preparing:counting down coroutine
//playing:normal game
//gameover:gameover
//pause:pause (game stop)
public enum GameState {none,Preparing,Playing,GameOver,Pause}
public enum HeroActionType {None,Run,Jump,Bend,Fall}public class GlobalManager : MonoBehaviour {//volume controllerpublic static ProjectVolume GlobalVol = ProjectVolume.FullVolume;//game state controllerpublic static GameState GlobalState = GameState.none;//count RedDiamondspublic static int RedDiamondCount=0;//count Distancepublic static int RunningDistance = 0;//7.28 action typespublic static HeroActionType ActionType = HeroActionType.None;}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Hero_Control_PC : MonoBehaviour {// public GameObject GoHero;public float FloRunningSpeed=1f;public float FloRotateSpeed = 1f;public float HeroJumpPower = 1f;//7.28 Animation Clipspublic AnimationClip AnimeRun;public AnimationClip AmimeJump;public AnimationClip AmimeBend;public AnimationClip AmimeFall;private Animation anime;private Rigidbody HeroRB;// Use this for initializationvoid Start () {anime = this.GetComponent<Animation>();HeroRB = this.GetComponent<Rigidbody>();//7.28 Get Key InputStartCoroutine("GetHeroActionInput");//play Hero's AnimationStartCoroutine("PlayHeroAnimation");}IEnumerator GetHeroActionInput(){yield return new WaitForEndOfFrame();while(true){yield return new WaitForSeconds(0.01f);if(GlobalManager.GlobalState==GameState.Playing){//Default setting:runningGlobalManager.ActionType = HeroActionType.Run;//Turningif(Input.GetKey(KeyCode.A)){this.transform.Rotate(Vector3.down * FloRotateSpeed);}else if (Input.GetKey(KeyCode.D)){this.transform.Rotate(Vector3.up * FloRotateSpeed);}//Jumpingelse if(Input.GetKeyDown(KeyCode.Space)){HeroRB.AddForce(Vector3.up * HeroJumpPower, ForceMode.Impulse);GlobalManager.ActionType = HeroActionType.Jump;yield return new WaitForSeconds(AmimeJump.length);}else if(Input.GetKeyDown(KeyCode.S)){}}}}
IEnumerator PlayHeroAnimation(){yield return new WaitForEndOfFrame();while(true){yield return new WaitForSeconds(0.01f);if (GlobalManager.GlobalState==GameState.Playing){switch(GlobalManager.ActionType){case HeroActionType.None:break;case HeroActionType.Run:anime.Play(AnimeRun.name);yield return new WaitForSeconds(AnimeRun.length);break;case HeroActionType.Jump:anime.Play(AmimeJump.name);yield return new WaitForSeconds(AmimeJump.length);break;case HeroActionType.Bend:break;case HeroActionType.Fall:break;}}}}// Update is called once per framevoid Update () {//7.24 latest updataif(GlobalManager.GlobalState==GameState.Playing){this.transform.Translate(Vector3.forward * FloRunningSpeed);}}}

Unity3D学习记录(跑酷小游戏第四阶段)相关推荐

  1. Unity3D学习记录 (跑酷小游戏完结)

    本日目标: 补充一些动作,添加触发检测 思考如何让游戏一直进行下去 处理一些bug,节约更多资源 项目: 我们为主角添加下铲和倒下的动作,首先来添加动作,定义动作剪辑片段. 在场景中把对应动画片段绑到 ...

  2. Unity3D学习之射箭小游戏

    一.了解基础知识 对于射箭小游戏来说,新增加了物理引擎的运用.物理引擎主要包括三个方面:Rigidbody.Collide.PhysicMaterial.其中,Collider是最基本的触发物理的条件 ...

  3. Unity3D学习:射击小游戏——飞碟世界

    游戏规则:游戏有三个关卡,每个关卡有四次发射机会,每次发射的飞碟大小颜色速度方向位置都不同,有50分初始分,每打中一个加10分,掉落一个在地减10分,第一二关都是90分过关,第三关70分过关,第一关每 ...

  4. 教你前端如何用js写一个跑酷小游戏

    在线体验地址:http://summer.pkec.net/ 源码地址:https://gitee.com/ihope_top/juejin-summer 前言 不知不觉夏天又到了,提到夏天你们能想到 ...

  5. 视频教程 | 3D 跑酷小游戏实战开发(下)

    上篇内容我们发布了 <视频教程 | 3D 跑酷小游戏实战开发(上)>,讲述了概述及创建.跑道创建.添加主角,今天我们继续学习:添加金币.处理碰撞.添加UI界面. 通过今天的学习,相信大家可 ...

  6. 一个跑酷小游戏的项目总结

    刚入职,项目经理要求我写一个跑酷小游戏,想看看我写代码水平 主要讲思路和问题 然后再问自己关于这个项目,想问的3个问题 思路 开始没有思路,给我看了微信比较火的猛男高跟鞋,但是人家是3d做的,我一定灵 ...

  7. Udacity利用深度学习玩赛车小游戏

    Udacity利用深度学习玩赛车小游戏 简单介绍 准备工作 训练网络 效果 简单介绍 这是Udacity无人驾驶课程里一个利用深度学习实现的玩赛车小游戏, 附上链接:github项目 原理就是玩家手动 ...

  8. 学习跃动小球小游戏(cocos creator)

    学习跃动小球小游戏 玩法:小球会不断的上下跳动,点击屏幕小球会加速掉落,下面的白色跳板一直在移动,小球需要准确的跳到跳板上才能得分. 效果图 [截图] ball脚本 小球碰撞回调 block脚本 初始 ...

  9. 【Devc++】双人跑酷小游戏1.3

    最近学了颜色函数, 我把双人跑酷小游戏的界面弄得好看了一点, 并把光标去掉了, 然而还是那么闪 代码 #include<bits/stdc++.h> #include<windows ...

最新文章

  1. Android.mk文件语法规范及使用模板 (转载)
  2. .vue文件中style标签的几个标识符
  3. Drupal的介绍----第一章:Drupal的介绍
  4. Windows 2008在域中不能更改密码策略解决方法
  5. 图像处理学习--前篇--像素相关
  6. 读”SQL Injection Pocket Reference”之摘录
  7. 【LOJ6072】苹果树【折半搜索】【矩阵树定理】【二项式反演】
  8. Java笔记-异常机制中try(...)中括号的用法
  9. div+css中常见的问题
  10. java rpc 框架 常用_常用的RPC架构系列---gRPC
  11. 网页视频之win7家庭版配置IIS
  12. linux系统常见的压缩命令,Linux 系统常见的压缩指令
  13. inner join 重复数据_pandas数据合并菜谱
  14. 三维计算机软件图,三维cad看图
  15. wxParse无法解析strong标签
  16. Arduino测量误差数据的处理——莱特、格拉布斯准则剔除异常数据
  17. pth文件转为onnx格式
  18. 进程管理API之pid_nr/pid_vnr/pid_nr_ns
  19. HLSL 的基础知识
  20. 判断输入数是奇数还是偶数

热门文章

  1. 进制转换--《十进制》
  2. UVA 10838 (alpha-bate剪枝搜索)
  3. 用python编程 商品打折_《Python编程入门指南》(上下册)
  4. 签到题:买房问题,利率计算
  5. 6-1 客户机类 (10 分)
  6. matlab做cdf图,matlab画CDF曲线
  7. php3D动画,html5的canvas实现几何模型3D运动动画效果
  8. 自动仓储系统(AS/RS)技术与装备
  9. 使用equinox开发osgi
  10. HDU 3271 SNIBB(数位DP+构造)