文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Unity怎么实现3D迷宫小游戏

2023-06-29 09:58

关注

这篇文章主要介绍了Unity怎么实现3D迷宫小游戏的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Unity怎么实现3D迷宫小游戏文章都会有所收获,下面我们一起来看看吧。

一、前言

闲来无事,从零开始整个《3D迷宫》小游戏。

二、构思

首先,要实现一个小游戏,心里肯定要有一个大概的想法,然后就是将想法完善起来。

我的想法就是一个用立体的墙搭建的迷宫,然后控制人物在迷宫中移动,最后找到出口,就这么简单。

当然,这是一个雏形,比如可以加点音效、背景、关卡、解密等。

那么整理一下实现思路就是:

OK,下面就正式开发。

三、正式开发

3-1、搭建场景

首先,新建个项目,我用了Unity 2019.4.7f1版本,项目名称跟位置按照自己的喜好设置即可:

Unity怎么实现3D迷宫小游戏

Unity怎么实现3D迷宫小游戏

接下来构建迷宫,先新建一个Plane,让它最够大,扩大10倍:

新建Cube,调整大小缩放,让它看起来像是一堵墙,然后构建迷宫:

Unity怎么实现3D迷宫小游戏

3-2、设置出入口

Unity怎么实现3D迷宫小游戏

放两个Cube,设置缩放,将出口名字改成Exit,这样就行了,到时候通过碰撞检测检测小球是否到达出口即可。

3-3、添加角色

在Hierarchy视图,右击选择3D Objcet→Capsule,新建一个球体,添加Rigibody组件:

Unity怎么实现3D迷宫小游戏

设置Drag抓地力为1。

就这样设置就行了,在实际运行中如果参数不合适还可以再调整。

将小球移动到入口的位置。

3-4、实现角色移动

这里直接使用官方的第一人称移动代码RigidbodyFirstPersonController .cs:

public class RigidbodyFirstPersonController : MonoBehaviour    {        [Serializable]        public class MovementSettings        {            public float ForwardSpeed = 8.0f;   // Speed when walking forward            public float BackwardSpeed = 4.0f;  // Speed when walking backwards            public float StrafeSpeed = 4.0f;    // Speed when walking sideways            public float RunMultiplier = 2.0f;   // Speed when sprinting        public 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_INPUT            private bool m_Running;#endif            public 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_INPUT            if (Input.GetKey(RunKey))            {            CurrentTargetSpeed *= RunMultiplier;            m_Running = true;            }            else            {            m_Running = false;            }#endif            }#if !MOBILE_INPUT            public 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 character            public float slowDownRate = 20f; // rate at which the controller comes to a stop when there is no input            public 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;#else            return 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 at                Vector3 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 paused            if (Mathf.Abs(Time.timeScale) < float.Epsilon) return;            // get the rotation before it's changed            float 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 looking                Quaternion 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 bottom        private 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 helper                Cursor.lockState = CursorLockMode.None;                Cursor.visible = true;            }        }        public void UpdateCursorLock()        {            //if the user set "lockCursor" we check & properly lock the cursos            if (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;        }    }

将所有的墙的父物体设置为地板。

设置摄像机的位置和父物体:

Unity怎么实现3D迷宫小游戏

运行程序:

Unity怎么实现3D迷宫小游戏

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);        }    }}

关于“Unity怎么实现3D迷宫小游戏”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“Unity怎么实现3D迷宫小游戏”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯