2D游戏开发模块梳理

image.png
Snap Seting 控制一次移动的步长,按住control 在移动工具中,一般设置为物体的长宽,批量复制

地形设计(Terrain)

image.png

笔刷

image.png
shift + mouse是降低
image.png

四种灯光

直射光
image.png
image.png
E.G

火堆

使用Lightmapping 贴图节约 性能

添加Lighting选项,将场景和灯光都选择为static
image.png

选择所有灯光Mode改为baked
image.png
Shadow Type选择 Hard 或者柔和的

粒子系统

火焰
image.png

导航系统

添加导航系统
image.png
对地形包括灯光所有选择为static
image.png

对象设置为不可到达(添加障碍物)
image.png
Inspector面板取消勾选对象的 Navigation static(取消障碍物)image.png
烘培完成
蓝色是可行走区域
image.png

添加玩家

为角色添加 Navi mesh agent
image.png
给玩家添加导航脚本

 void Update()
    {
        //使用射线检测 
        if (Input.GetMouseButton(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//屏幕坐标转换成射线
            RaycastHit hit; //保持碰撞信息
            if(Physics.Raycast(ray, out hit))
            {
                Debug.Log(hit.point);
                agent.SetDestination(hit.point);//导航
            }//射线检测
            
        }
    }

image.png

控制相机跟随(视野问题)

public class FollowTarget : MonoBehaviour
{
    public Transform playertransform;
    private Vector3 offset;
    // Start is called before the first frame update
    void Start()
    {
       offset = transform.position - playertransform.position;//设置相机跟随距离
    }

    // Update is called once per frame
    void Update()
    {
        transform.position = playertransform.position + offset;//相机跟随
    }
}

把角色在检视窗口赋值给playertransfrom
注意:点击后 人物移动的速度 符合牛顿定律(第1 第2)

TileMap画板使用(2D)

Hirarchy创建
image.png
然后创建调色板,拖入Sprite图
image.png
鼠标点击单元图,进行粉刷
image.png

切割精灵图制作瓦片集

  1. 选择精灵图集,设置type = multipe类型
  2. image.png
  3. 选择切割方式,Apply,然后拖入调色板 ,灵活配图

image.png
Edit按下是对调色板中的瓦片进行操作,抬起是对scene(上方)进行操作
image.png

渲染顺序

实现ruby在盒子下方时脑袋挡住盒子,在盒子上方(后面)被挡住腿,远近的实现
image.png
image.pngimage.png

细节

image.png
设置盒子的Pivot

刚体

  • 尽量使用刚体控制移动,不然移动脚本可能造成接触物体发生抖动
  • 2D记得冻结Y轴旋转,不然碰撞后发生 侧旋

场景碰撞器

为Tilemap添加tilemap collider 2D
更改Tile图片的的碰撞类型为None ,河流 石头 是sprite
image.png

image.png

再更改Rigidbody2d 为static
image.png

敌人

伤害区域

ctrl + k f 格式化代码
在chactrar 文件夹里设置敌人的 Pivot 为脚部
调整collider的大小为脚部

敌人的移动控制脚本

  1. 先创建Animator Controller ,挂载到GO上
  2. 再创建Animation,

image.png
编辑精灵图的动画
image.pngimage.png
导入精灵图集的单帧动作动画,调整间隔和顺序
image.png
编辑动画之间的间隔
image.png
状态机连线,添加条件
在脚本中,设置相应参数
使用混合树

玩家

玩家控制脚本

    private Vector2 lookDirection = new Vector2(1,0);//Ruby朝向向量
void Update(){
    //玩家输入监听
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        Vector2 move = new Vector2(horizontal,vertical);

     if (!Mathf.Approximately(move.x,0)||!Mathf.Approximately(move.y,0))
        {
            //lookDirection.Set(move.x,move.y);
            lookDirection = move;
            lookDirection.Normalize();
            if (!walkAudioSource.isPlaying)
            {
                walkAudioSource.clip = walkSound;
                walkAudioSource.Play();
            }                      
        }
        else
        {
            walkAudioSource.Stop();
        }

 //动画的控制
        animator.SetFloat("Look X",lookDirection.x);//Look X ,Look Y混合树参数
        animator.SetFloat("Look Y",lookDirection.y);
        animator.SetFloat("Speed",move.magnitude);

        //移动
        Vector2 position = transform.position;


     //Ruby的目标位置
        position += speed * move * Time.deltaTime;
        //transform.position  = position;
    //Ruby移动到目标位置
        rigidbody2d.MovePosition(position);

    
}

子弹脚本发射

        #Ruby脚本中 动态创建子弹对象

        GameObject projectileObject = Instantiate(projectilePrefab,
            rigidbody2d.position+Vector2.up*0.5f,Quaternion.identity);//克隆方法

        Projectile projectile= projectileObject.GetComponent<Projectile>();//获取子弹脚本组件

        projectile.Launch(lookDirection,300);//调用子弹脚本创建一个子弹
        animator.SetTrigger("Launch");




    	 //按键绑定
        if (Input.GetKeyDown(KeyCode.H))
        {
            Launch();
        }


    	#Bullet脚本中
	     public void Launch(Vector2 direction,float force) //子弹发射方法(Ruby调用)
    {
        rigidbody2d.AddForce(direction*force);//自身刚体调用自己的施加力的方式
    }

   		 private void OnCollisionEnter2D(Collision2D collision)
    {
        //Debug.Log("当前子弹碰撞到的游戏物体是:"+collision.gameObject);
        EnemyController enemyController = collision.gameObject.
            GetComponent<EnemyController>();
        if (enemyController!=null)
        {
            enemyController.Fix();
        }
        Destroy(gameObject);//子弹销毁
    }

 private void Update()
    {
        if (transform.position.magnitude>100) //子弹不触碰,长距离销毁 transform.position.magnitude 距离向量的模长
        {
            Destroy(gameObject);
        }
    }


        

添加子弹交互动画

通过层级系统 筛选碰撞单元

添加层级
image.png
image.png
image.png

粒子系统

给对象添加粒子系统
image.png
image.png
更改参数
image.png
上传特效图片,选择Start Frame区间,下拉列表,随机在两个之间

血条

使用MASK 制作血条
image.png
image.png

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UIHealthBar : MonoBehaviour
{
    public Image mask;
    private float originalSize;

    public static UIHealthBar instance { get; private set; }//单例模式,可全局访问

    public bool hasTask;
    //public bool ifCompleteTask;
    public int fixedNum;

    private void Awake() //单例模式的实例化
    {
        instance = this;
    }

    // Start is called before the first frame update
    void Start()
    {
        originalSize = mask.rectTransform.rect.width;
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    /// <summary>
    /// 血条UI填充显示
    /// </summary>
    /// <param name="fillPercent">填充百分比</param>
    public void SetValue(float fillPercent)
    {
        mask.rectTransform.SetSizeWithCurrentAnchors(RectTransform.
            Axis.Horizontal,originalSize*fillPercent);
    }
}

射线检测

NPC对话系统

 if (Input.GetKeyDown(KeyCode.T))
        {
            RaycastHit2D hit = Physics2D.Raycast(rigidbody2d.position+Vector2.up*0.2f,//添加V2.up原因是角色初始锚点在脚部,设置后射线初始位置在胸口
                lookDirection,1.5f,LayerMask.GetMask("NPC"));
            //存储触碰物体的信息
            if (hit.collider!=null)
            {
                NPCDialog npcDialog = hit.collider.GetComponent<NPCDialog>();//获取NPC身上控制对话的脚本
                if (npcDialog!=null)
                {
                    npcDialog.DisplayDialog();
                }
            }
        }

对话框脚本中使用计时器,确定对话消失时间

void Update()
    {
        if (timerDisplay>=0)
        {
            timerDisplay -= Time.deltaTime;
            if (timerDisplay<0)
            {
                dialogBox.SetActive(false);
            }
        }
    }

    public void DisplayDialog() //显示当前对话框
    {
        timerDisplay = displayTime;
        dialogBox.SetActive(true);//激活对话框
        UIHealthBar.instance.hasTask = true;
        if (UIHealthBar.instance.fixedNum>=5)
        {
            //已经完成任务,需要修改对话框内容
            dialogText.text = "哦,伟大的Ruby,谢谢你,你真的太棒了!";
            if (!hasPlayed)
            {
                audioSource.PlayOneShot(completeTaskclip);
                hasPlayed = true;
            }
            
        }
    }

对话框画板 设置为世界模式
image.png
血条 和 玩家信息画布应该是Overlay模式
Canvas子对象如果填充Canvas,在锚点视图,点ctrl,选择右下角全充满
子对象选择Image导入对话框背景图

背景音乐与音效

AudioClip(音频剪辑资源)

播放条件需要一个Audio Source
image.png
需要一个对象有Audio Listener(一般为相机)
image.png
image.png

AudioSource组件

 public void PlaySound(AudioClip audioClip)//播放音效
    {
        audioSource.PlayOneShot(audioClip);//PlayOneShot表示只播放一次
    }
  if (!Mathf.Approximately(move.x,0)||!Mathf.Approximately(move.y,0))//Approximately()判断浮点数是否近似相等
        {
            //lookDirection.Set(move.x,move.y);
            lookDirection = move;
            lookDirection.Normalize();
            if (!walkAudioSource.isPlaying) //移动音效
            {
                walkAudioSource.clip = walkSound;
                walkAudioSource.Play();
            }                      
        }
        else
        {
            walkAudioSource.Stop();
        }

人物落地音效实现

干扰:上半身碰撞地形/地面行走

  • Jump_Time是人物一次起跳后在空中停留的时间
  • 引入计时器,玩家起跳后开始计时Clock_Time +=Time.deltaTime
  • 接触地形后,判断Clock_Time与Jump_Time关系,测试,选取最小阈值【e.g.起跳上地形上,接触时间可能比较小】
  • Clock_Time大于最小阈值判断为落地
  • 播放
private AudioClip landClip;
landClip = Resources.Load<AudioClip>("Gris/Audioclips/Land");//落地音效
AudioSource.PlayClipAtPoint(landClip,transform.position);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值