【Unity3D开发小游戏】Unity3D开发《3D迷宫》小游戏
推荐阅读
- CSDN主页
- GitHub开源地址
- Unity3D插件分享
- 简书地址
- 我的个人博客
- QQ群:1040082875
大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。
一、前言
闲来无事,从零开始整个《3D迷宫》小游戏。
本篇文章会详细介绍构思、实现思路,希望可以帮助到有缘人。
二、构思
首先,要实现一个小游戏,心里肯定要有一个大概的想法,然后就是将想法完善起来。
我的想法就是一个用立体的墙搭建的迷宫,然后控制人物在迷宫中移动,最后找到出口,就这么简单。
当然,这是一个雏形,比如可以加点音效、背景、关卡、解密等。
那么整理一下实现思路就是:
- 构建3D迷宫
- 实现人物移动
- 实现出入口逻辑
OK,下面就正式开发。
三、正式开发
3-1、搭建场景
首先,新建个项目,我用了Unity 2019.4.7f1
版本,项目名称跟位置按照自己的喜好设置即可:
接下来构建迷宫,先新建一个Plane,让它最够大,扩大10倍:
新建Cube,调整大小缩放,让它看起来像是一堵墙,然后构建迷宫:
3-2、设置出入口
放两个Cube,设置缩放,将出口名字改成Exit,这样就行了,到时候通过碰撞检测检测小球是否到达出口即可。
3-3、添加角色
在Hierarchy视图,右击选择3D Objcet→Capsule,新建一个球体,添加Rigibody组件:
设置Drag抓地力为1。
就这样设置就行了,在实际运行中如果参数不合适还可以再调整。
将小球移动到入口的位置。
3-4、实现角色移动
这里直接使用官方的第一人称移动代码RigidbodyFirstPersonController .cs:
public class RigidbodyFirstPersonController : MonoBehaviour{[Serializable]public class MovementSettings{public float ForwardSpeed = 8.0f; // Speed when walking forwardpublic float BackwardSpeed = 4.0f; // Speed when walking backwardspublic float StrafeSpeed = 4.0f; // Speed when walking sidewayspublic float RunMultiplier = 2.0f; // Speed when sprintingpublic KeyCode RunKey = KeyCode.LeftShift;public float JumpForce = 30f;public AnimationCurve SlopeCurveModifier = new AnimationCurve(new Keyframe(-90.0f, 1.0f), new Keyframe(0.0f, 1.0f), new Keyframe(90.0f, 0.0f));[HideInInspector] public float CurrentTargetSpeed = 8f;#if !MOBILE_INPUTprivate bool m_Running;
#endifpublic void UpdateDesiredTargetSpeed(Vector2 input){if (input == Vector2.zero) return;if (input.x > 0 || input.x < 0){//strafeCurrentTargetSpeed = StrafeSpeed;}if (input.y < 0){//backwardsCurrentTargetSpeed = BackwardSpeed;}if (input.y > 0){//forwards//handled last as if strafing and moving forward at the same time forwards speed should take precedenceCurrentTargetSpeed = ForwardSpeed;}
#if !MOBILE_INPUTif (Input.GetKey(RunKey)){CurrentTargetSpeed *= RunMultiplier;m_Running = true;}else{m_Running = false;}
#endif}#if !MOBILE_INPUTpublic bool Running{get { return m_Running; }}
#endif}[Serializable]public class AdvancedSettings{public float groundCheckDistance = 0.01f; // distance for checking if the controller is grounded ( 0.01f seems to work best for this )public float stickToGroundHelperDistance = 0.5f; // stops the characterpublic float slowDownRate = 20f; // rate at which the controller comes to a stop when there is no inputpublic bool airControl; // can the user control the direction that is being moved in the air[Tooltip("set it to 0.1 or more if you get stuck in wall")]public float shellOffset; //reduce the radius by that ratio to avoid getting stuck in wall (a value of 0.1f is nice)}public Camera cam;public MovementSettings movementSettings = new MovementSettings();public MouseLook mouseLook = new MouseLook();public AdvancedSettings advancedSettings = new AdvancedSettings();private Rigidbody m_RigidBody;private CapsuleCollider m_Capsule;private float m_YRotation;private Vector3 m_GroundContactNormal;private bool m_Jump, m_PreviouslyGrounded, m_Jumping, m_IsGrounded;public Vector3 Velocity{get { return m_RigidBody.velocity; }}public bool Grounded{get { return m_IsGrounded; }}public bool Jumping{get { return m_Jumping; }}public bool Running{get{#if !MOBILE_INPUTreturn movementSettings.Running;
#elsereturn false;
#endif}}private void Start(){m_RigidBody = GetComponent<Rigidbody>();m_Capsule = GetComponent<CapsuleCollider>();mouseLook.Init (transform, cam.transform);}private void Update(){RotateView();if (CrossPlatformInputManager.GetButtonDown("Jump") && !m_Jump){m_Jump = true;}}private void FixedUpdate(){GroundCheck();Vector2 input = GetInput();if ((Mathf.Abs(input.x) > float.Epsilon || Mathf.Abs(input.y) > float.Epsilon) && (advancedSettings.airControl || m_IsGrounded)){// always move along the camera forward as it is the direction that it being aimed atVector3 desiredMove = cam.transform.forward*input.y + cam.transform.right*input.x;desiredMove = Vector3.ProjectOnPlane(desiredMove, m_GroundContactNormal).normalized;desiredMove.x = desiredMove.x*movementSettings.CurrentTargetSpeed;desiredMove.z = desiredMove.z*movementSettings.CurrentTargetSpeed;desiredMove.y = desiredMove.y*movementSettings.CurrentTargetSpeed;if (m_RigidBody.velocity.sqrMagnitude <(movementSettings.CurrentTargetSpeed*movementSettings.CurrentTargetSpeed)){m_RigidBody.AddForce(desiredMove*SlopeMultiplier(), ForceMode.Impulse);}}if (m_IsGrounded){m_RigidBody.drag = 5f;if (m_Jump){m_RigidBody.drag = 0f;m_RigidBody.velocity = new Vector3(m_RigidBody.velocity.x, 0f, m_RigidBody.velocity.z);m_RigidBody.AddForce(new Vector3(0f, movementSettings.JumpForce, 0f), ForceMode.Impulse);m_Jumping = true;}if (!m_Jumping && Mathf.Abs(input.x) < float.Epsilon && Mathf.Abs(input.y) < float.Epsilon && m_RigidBody.velocity.magnitude < 1f){m_RigidBody.Sleep();}}else{m_RigidBody.drag = 0f;if (m_PreviouslyGrounded && !m_Jumping){StickToGroundHelper();}}m_Jump = false;}private float SlopeMultiplier(){float angle = Vector3.Angle(m_GroundContactNormal, Vector3.up);return movementSettings.SlopeCurveModifier.Evaluate(angle);}private void StickToGroundHelper(){RaycastHit hitInfo;if (Physics.SphereCast(transform.position, m_Capsule.radius * (1.0f - advancedSettings.shellOffset), Vector3.down, out hitInfo,((m_Capsule.height/2f) - m_Capsule.radius) +advancedSettings.stickToGroundHelperDistance, Physics.AllLayers, QueryTriggerInteraction.Ignore)){if (Mathf.Abs(Vector3.Angle(hitInfo.normal, Vector3.up)) < 85f){m_RigidBody.velocity = Vector3.ProjectOnPlane(m_RigidBody.velocity, hitInfo.normal);}}}private Vector2 GetInput(){Vector2 input = new Vector2{x = CrossPlatformInputManager.GetAxis("Horizontal"),y = CrossPlatformInputManager.GetAxis("Vertical")};movementSettings.UpdateDesiredTargetSpeed(input);return input;}private void RotateView(){//avoids the mouse looking if the game is effectively pausedif (Mathf.Abs(Time.timeScale) < float.Epsilon) return;// get the rotation before it's changedfloat oldYRotation = transform.eulerAngles.y;mouseLook.LookRotation (transform, cam.transform);if (m_IsGrounded || advancedSettings.airControl){// Rotate the rigidbody velocity to match the new direction that the character is lookingQuaternion velRotation = Quaternion.AngleAxis(transform.eulerAngles.y - oldYRotation, Vector3.up);m_RigidBody.velocity = velRotation*m_RigidBody.velocity;}}/// sphere cast down just beyond the bottom of the capsule to see if the capsule is colliding round the bottomprivate void GroundCheck(){m_PreviouslyGrounded = m_IsGrounded;RaycastHit hitInfo;if (Physics.SphereCast(transform.position, m_Capsule.radius * (1.0f - advancedSettings.shellOffset), Vector3.down, out hitInfo,((m_Capsule.height/2f) - m_Capsule.radius) + advancedSettings.groundCheckDistance, Physics.AllLayers, QueryTriggerInteraction.Ignore)){m_IsGrounded = true;m_GroundContactNormal = hitInfo.normal;}else{m_IsGrounded = false;m_GroundContactNormal = Vector3.up;}if (!m_PreviouslyGrounded && m_IsGrounded && m_Jumping){m_Jumping = false;}}}
MouseLook.cs:
public class MouseLook{public float XSensitivity = 2f;public float YSensitivity = 2f;public bool clampVerticalRotation = true;public float MinimumX = -90F;public float MaximumX = 90F;public bool smooth;public float smoothTime = 5f;public bool lockCursor = true;private Quaternion m_CharacterTargetRot;private Quaternion m_CameraTargetRot;private bool m_cursorIsLocked = true;public void Init(Transform character, Transform camera){m_CharacterTargetRot = character.localRotation;m_CameraTargetRot = camera.localRotation;}public void LookRotation(Transform character, Transform camera){float yRot = CrossPlatformInputManager.GetAxis("Mouse X") * XSensitivity;float xRot = CrossPlatformInputManager.GetAxis("Mouse Y") * YSensitivity;m_CharacterTargetRot *= Quaternion.Euler (0f, yRot, 0f);m_CameraTargetRot *= Quaternion.Euler (-xRot, 0f, 0f);if(clampVerticalRotation)m_CameraTargetRot = ClampRotationAroundXAxis (m_CameraTargetRot);if(smooth){character.localRotation = Quaternion.Slerp (character.localRotation, m_CharacterTargetRot,smoothTime * Time.deltaTime);camera.localRotation = Quaternion.Slerp (camera.localRotation, m_CameraTargetRot,smoothTime * Time.deltaTime);}else{character.localRotation = m_CharacterTargetRot;camera.localRotation = m_CameraTargetRot;}UpdateCursorLock();}public void SetCursorLock(bool value){lockCursor = value;if(!lockCursor){//we force unlock the cursor if the user disable the cursor locking helperCursor.lockState = CursorLockMode.None;Cursor.visible = true;}}public void UpdateCursorLock(){//if the user set "lockCursor" we check & properly lock the cursosif (lockCursor)InternalLockUpdate();}private void InternalLockUpdate(){if(Input.GetKeyUp(KeyCode.Escape)){m_cursorIsLocked = false;}else if(Input.GetMouseButtonUp(0)){m_cursorIsLocked = true;}if (m_cursorIsLocked){Cursor.lockState = CursorLockMode.Locked;Cursor.visible = false;}else if (!m_cursorIsLocked){Cursor.lockState = CursorLockMode.None;Cursor.visible = true;}}Quaternion ClampRotationAroundXAxis(Quaternion q){q.x /= q.w;q.y /= q.w;q.z /= q.w;q.w = 1.0f;float angleX = 2.0f * Mathf.Rad2Deg * Mathf.Atan (q.x);angleX = Mathf.Clamp (angleX, MinimumX, MaximumX);q.x = Mathf.Tan (0.5f * Mathf.Deg2Rad * angleX);return q;}}
将所有的墙的父物体设置为地板。
设置摄像机的位置和父物体:
运行程序:
3-5、出入口逻辑
出口用碰撞检测,新建脚本ExitControl.cs,编辑代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;public class ExitControl : MonoBehaviour
{void OnCollisionEnter(Collider col){if (col.gameObject.name == "Capsule"){SceneManager.LoadScene(SceneManager.GetActiveScene().name);}}
}
将代码附给Exit对象。
结束了。
四、总结
本文实现了一个《3D迷宫》小游戏。
首先,搭建场景,然后实现角色移动,出入口逻辑。
整天代码比较简单,官方的移动代码也可以学习一下。
【Unity3D开发小游戏】Unity3D开发《3D迷宫》小游戏相关推荐
- 小虫子的冒险_Python迷宫类型游戏
这是一个用Python制作的迷宫游戏,需要基于Python海龟画图模块精灵模块支持,安装方法为 pip install sprites. 如果安装很慢,请联系李兴球,微信scratch8, 在这个游戏 ...
- 微信小游戏|unity搭建3D篮球小游戏场景
欢迎点击「算法与编程之美」↑关注我们! 本文首发于微信公众号:"算法与编程之美",欢迎关注,及时了解更多此系列文章. 欢迎加入团队圈子!与作者面对面!直接点击! 问题描述 上一次小 ...
- html枪战游戏代码大全,3D枪战射击游戏cs简单版源代码
[实例简介] 3D枪战射击游戏cs简单版源代码,本代码用opengl开发,使用vc6.0适用于初学者 [实例截图] [核心代码] vccs └── vccs ├── CDSound.cpp ├── C ...
- 计算机3d 游戏制作,揭秘3D电影、游戏角色的制作过程!
原标题:揭秘3D电影.游戏角色的制作过程! 从来没有接触过建模的小白们是否都很好奇,3D电影.游戏角色是怎样做出来的呢?比如说<捉妖记>里的胡巴.今年大火的国漫<哪吒>,< ...
- android飞行射击游戏代码,android 3D飞行射击游戏《夜鹰行动》源码
压缩包内容概览: android 3D飞行射击游戏<夜鹰行动>源码-airattacker ; 清单 ; 资产 ; 项目 ; 飞骥11 ; 飞骥22 ; 飞骥33 ; 折叠按钮 ; 弗雷格 ...
- 《游戏学习》| 3d网页小游戏 | 公路赛车 源码
游戏介绍 基于three.js实现的3d网页游戏,适配移动端和pc端网页,可以选择简单.普通.困难.地狱四个游戏难度等级,通过控制左右,超过其他车辆得分. 游戏截图 游戏主页 游戏界面 结束界面 项目 ...
- python语言迷宫游戏_一个Python迷宫小游戏
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 # 设置屏幕宽度和高度为全局变量 global screen_width screen_width = 800 global screen_height ...
- c语言简单射击小游戏源程序,简单的迷宫小游戏 C语言程序源代码
#include #include #include #include #define Height 31 //迷宫的高度,必须为奇数 #define Width 25 //迷宫的宽度,必须为奇数 # ...
- qt 3d迷宫游戏_《加雷利亚的地下迷宫与魔女的旅团》最新情报公布
日本一旗下最新作品<加雷利亚的地下迷宫与魔女的旅团(Coven and labyrinth of Galleria)>公布了有关本作角色和新登场Facet的最新情报,让我们一起来看看吧! ...
- 大型3d射击类游戏源码【突击风暴】,中文版本,可私服
<突击风暴>(英文名称:Sudden Attack)是由韩国GAMEHI公司制作,盛大游戏运营的第一人称射击类网络游戏.<突击风暴>于2011年6月9日开服,2012年12月3 ...
最新文章
- Silverlight中的拖拽实现的图片上传---1
- linux elf 文件查看工具 readelf
- 微信小程序开发记录一,开发工具的使用
- 25个好用到爆的一行Python代码,建议收藏
- 前端学习(3303):函数组件组件子组件useRef聚焦
- SpannableString与SpannableStringBuilder使用
- rtsp,rtp,gb28181直接转化为html5播放(二)
- owncloud mysql版本_Linux Deploy Owncloud php7.0+apache2+mysql5.7+owncloud9.1
- java计算器课程报告_java课程设计报告计算器设计.doc
- 用python实现pdf转word(带格式)_Python 实现加密过的PDF文件转WORD格式
- 人行征信报告介绍(一)
- linux文件权限数字754,linux555、644、666、755、777权限详解数字代表什么意思
- 万字长文讲述:任正非,“血洗”华为
- c语言第五章答案许合利,C语言习题答案贾宗璞许合利较全-.doc
- ESP8266人体感应项目
- AHK 键盘控制鼠标点击屏幕不同位置
- 这位闯进程序员界的维密天使,她到底可以编出什么?!
- jQuery如何根据元素值删除数组元素
- 模块-E18-D80NK红外避障传感器
- Android 高质量开发之崩溃优化,2020-2021字节跳动Android面试真题解析