文章目录
0.开发流程一、二
开发流程一:https://blog.csdn.net/xiji333/article/details/109621328
开发流程二:https://blog.csdn.net/xiji333/article/details/109955327
1.视觉差Parallax
这一节是为了让你的 2 D 2D 2D平板看起来更有层次感,简单来说就是让背景或者其它的物体以不同于摄像机的速率移动。想要实现这个效果的可以去看视频。
2.主菜单MainMenu
这一节我们来制作主菜单。涉及到 U I UI UI的 p a n e l 、 b u t t o n panel、button panel、button,以及动画效果。
可以设置 b u t t o n button button的各种属性,比如默认颜色,高亮颜色,点击时的颜色,不可用时的颜色等等:
T e x t M e s h P r o TextMeshPro TextMeshPro文本也可以设置很多属性,比如字体、阴影、颜色(可以设置渐变色)、外发光等等:
接下来就是给按钮添加监听了:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class MainMenu : MonoBehaviour
{
public void Play()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
}
public void Quit()
{
#if UNITY_EDITOR
UnityEditor.EditorApplication.isPlaying = false;
#else
Application.Quit();
#endif
}
}
把它挂在到 p a n e l panel panel上,然后给按钮增加监听:
然后就可以啦,注意一定不要删除 E v e n t S y s t e m EventSystem EventSystem这个对象。
3.暂停菜单&AudioMixer&滑动条控制音量
这一节我们将制作一个暂停菜单,虽然比较丑不过主要是为了学一下怎么通过它来控制我们游戏的声音:
把下面的代码挂到 P a u s e P a n e l PausePanel PausePanel上,并设置两个按钮的监听:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PausePanel : MonoBehaviour
{
public void Pause()
{
gameObject.SetActive(true);
//慢动作或者加速也可以通过设置这个参数实现!
Time.timeScale = 0f;
}
public void Continue()
{
gameObject.SetActive(false);
Time.timeScale = 1f;
}
}
接下来是关于 A u d i o M i x e r Audio\ Mixer Audio Mixer的介绍。首先自己创建一个 A u d i o M i x e r Audio\ Mixer Audio Mixer,并从菜单打开相关的窗口:
A u d i o M i x e r Audio\ Mixer Audio Mixer可以混合调节多个 A u d i o S o u r c e Audio\ Source Audio Source,只需要修改它的 O u t p u t Output Output:
你对 A u d i o M i x e r Audio\ Mixer Audio Mixer的设置(音量、音效等等)会影响所有关联到它的 A u d i o S o u r c e Audio\ Source Audio Source的最终播放效果:
那么我把滑条的范围设置到 [ − 80 , 20 ] [-80,20] [−80,20],再把当前滑条对应的值设置到这里就可以控制音量的大小了。注意 A u d i o M i x e r Audio\ Mixer Audio Mixer是没有办法直接挂载脚本的,我们需要把它的某些属性公开出去(即可以通过代码中的 A u d i o M i x e r Audio\ Mixer Audio Mixer对象访问),首先点击想要公开出去的属性:
右键选择:
在这里可以看到公开出来的属性,还可以修改名字:
现在来修改代码吧:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;
public class PausePanel : MonoBehaviour
{
public AudioMixer mainAudioMixer;
public void Pause()
{
gameObject.SetActive(true);
//慢动作或者加速也可以通过设置这个参数实现!
Time.timeScale = 0f;
}
public void Continue()
{
gameObject.SetActive(false);
Time.timeScale = 1f;
}
public void SetVolume(float value)
{
//注意这里的第一个参数要和公开出来的属性的名称一致
mainAudioMixer.SetFloat("MainVolume", value);
}
}
设置滑动条的监听:
注意此处不要选择下面的那个同名函数,那个只能设置一个值,上面这个是跟随滑动条动态设置的。
接下来我们再增加一个滑动条,用来控制人物跳跃、受伤、攻击、敌人爆炸的音效的大小:
新增一个 E f f e c t Effect Effect分组,并设置相关音源的输出、滑动条监听等:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;
public class PausePanel : MonoBehaviour
{
public AudioMixer mainAudioMixer;
public void Pause()
{
gameObject.SetActive(true);
//慢动作或者加速也可以通过设置这个参数实现!
Time.timeScale = 0f;
}
public void Continue()
{
gameObject.SetActive(false);
Time.timeScale = 1f;
}
public void SetMainVolume(float value)
{
//注意这里的第一个参数要和公开出来的属性的名称一致
mainAudioMixer.SetFloat("MainVolume", value);
}
public void SetEffectVolume(float value)
{
mainAudioMixer.SetFloat("EffectVolume", value);
}
}
游玩游戏后你会发现,第二个滑动条只影响分组中与 E f f e c t Effect Effect相关的音源,第一个滑动条不仅影响与 M a s t e r Master Master相关的,还影响与 E f f e c t Effect Effect相关的。那么我们可以得出一个结论,一个分组中的主 M i x e r Mixer Mixer影响其余所有 M i x e r Mixer Mixer。
4.手机控制|触控操作|真机测试
看视频吧:https://www.bilibili.com/video/BV1GJ411u75o?p=2。
5.单向平台
如图所示,他目前是一个普通的平台,即玩家从下面不能直接跳上去:
给它添加一个 P l a t f o r m E f f e c t o r 2 D Platform\ Effector\ 2D Platform Effector 2D组件,同时勾选碰撞体的 U s e d B y E f f e c t o r Used\ By\ Effector Used By Effector:
现在人物就可以从下面直接跳上来了。
6.移动手感&多段跳
F i x e d U p d a t e FixedUpdate FixedUpdate的时间间隔是固定的, U p d a t e Update Update的时间间隔是不固定的。当你用代码监听用户的按键( G e t B u t t o n 、 G e t K e y GetButton、GetKey GetButton、GetKey),且希望得到一个实时的反馈时,你需要使用 U p d a t e Update Update;所有跟物理有关的东西应该放到 F i x e d U p d a t e FixedUpdate FixedUpdate中。
由于跳跃和下蹲都是需要实时响应的,所以我们把这部分的代码放到 U p d a t e Update Update中,而移动一般来说都是需要用户持续按下方向键的,我们可以把这部分代码放到 F i x e d U p d a t e FixedUpdate FixedUpdate中。下面的代码实现了二段跳,我自己感觉手感还是可以的,注意要把 r i g i d b o d y rigidbody rigidbody中的重力系数调到 2 2 2。不过下面的代码也不是很完美,依然还有很多需要打磨的地方,比如动画状态机中 F a l l Fall Fall到 H u r t Hurt Hurt的切换,蹲下的时候不能跳跃,跳跃的时候不能蹲下之类的。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class PlayerController : MonoBehaviour
{
private Rigidbody2D rb2d;
private Animator animator;
private BoxCollider2D boxCollider2D;
[SerializeField]
private int cherry = 0;
[SerializeField]
private int jumpCount = 2;
[SerializeField]
private bool isHurt = false;
private Vector2 initBoxCollider2DOffset;
private Vector2 initBoxCollider2DSize;
private Vector2 crouchBoxCollider2DOffset = new Vector2(0, -0.57f);
private Vector2 crouchBoxCollider2DSize = new Vector2(0.92f, 0.85f);
public Text cherryText;
public float speed = 5f;
public float jumpForce = 8f;
public LayerMask ground;
public AudioSource jumpAudio;
public AudioSource hurtAudio;
public AudioSource pickCherryAudio;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
animator = GetComponent<Animator>();
boxCollider2D = GetComponent<BoxCollider2D>();
initBoxCollider2DOffset = boxCollider2D.offset;
initBoxCollider2DSize = boxCollider2D.size;
}
// Update is called once per frame
void Update()
{
Jump();
Crouch();
SwitchAnimation();
}
private void FixedUpdate()
{
if (!isHurt)//非受伤状态
{
Movement();
}
}
void Jump()
{
if (boxCollider2D.IsTouchingLayers(ground) && !animator.GetBool("jumping"))
jumpCount = 2;
if (Input.GetButtonDown("Jump") && jumpCount > 0)
{
rb2d.velocity = new Vector2(rb2d.velocity.x, jumpForce);
animator.SetBool("jumping", true);
jumpAudio.Play();
--jumpCount;
}
}
void Movement()
{
float horizontalMove = Input.GetAxis("Horizontal");
int faceDirection = (int)Input.GetAxisRaw("Horizontal");
rb2d.velocity = new Vector2(faceDirection * speed, rb2d.velocity.y);
animator.SetFloat("running", Mathf.Abs(horizontalMove));
if (faceDirection != 0)
{
transform.localScale = new Vector3(faceDirection, 1, 1);
}
}
void Crouch()
{
//头顶上没有障碍物
if (!Physics2D.OverlapCircle(transform.position, 0.4f, ground))
{
//持续按下
if (Input.GetButton("Crouch"))
{
animator.SetBool("crouching", true);
boxCollider2D.offset = crouchBoxCollider2DOffset;
boxCollider2D.size = crouchBoxCollider2DSize;
}
else
{
animator.SetBool("crouching", false);
boxCollider2D.offset = initBoxCollider2DOffset;
boxCollider2D.size = initBoxCollider2DSize;
}
}
}
void SwitchAnimation()
{
if (rb2d.velocity.y < 0 && !boxCollider2D.IsTouchingLayers(ground)) //y轴速度<0且没有接触到地面时
{
animator.SetBool("falling", true);
}
if (animator.GetBool("jumping")) //跳跃状态
{
if (rb2d.velocity.y < 0)
{
animator.SetBool("jumping", false);
animator.SetBool("falling", true);
}
}
else if (animator.GetBool("falling")) //下落状态
{
if (boxCollider2D.IsTouchingLayers(ground))
{
animator.SetBool("falling", false);
}
}
else if (isHurt) //受伤状态
{
animator.SetBool("hurt", true);
int sign = rb2d.velocity.x < 0 ? -1 : 1;
rb2d.velocity += new Vector2(speed * Time.deltaTime, 0f) * -sign;
if (Mathf.Abs(rb2d.velocity.x) < 0.1f)
{
isHurt = false;
animator.SetBool("hurt", false);
}
}
}
7.音效管理SoundManager(Static)
其实就是创建了一个单例类用来管理场景中的声音,想学的可以看视频学习。我觉得它的不足之处就是同一时间只能播放一个 c l i p clip clip,所以就不写啦。
8.End 游戏生成Build
完结撒花~