Unity3D自制横版闯关游戏手册(1)

Unity3D自制横版闯关游戏手册(1)

提要:因为某些原因把unity的版本从5.0一口气更到了2017.3,东西多了不少,悲剧的是还在写的项目用的插件全都检测不了,反复删除和安装无效果后决定把已经写好的内容重新写一次,刚好之前写的东西因为是边学边写的,所以其实效果和实现方法都有些不太满意,资源的管理也比较混乱。记录一下这一次的重写,希望能帮助自己理清思路,好,那就赶紧开始吧
Notice:本项目所用资源均来源于互联网,本项目仅用作学习与交流

开始界面:
create一个canve,设定下自适应拉伸

设置画布大小为960*540,与宽高自适应,16:9适应大部分手机。分辨率请自己记住自己的设定值,后面坐标转换时会用上
这里写图片描述
摆好布局,设置两个按钮,touch是透明的用来检测点击的按钮
下面做抚摸屏幕的闪烁动画,原本我是用代码写的,不过后来发现这种小效果也用脚本的话,代码管理会非常混乱(取名品味太差星人),干脆一律用amator控制animation算了,又快又容易管理,动画文件即使忘记了他是什么动作,播放一下就能立马懂,不像代码即使有注释还得看半天。我们加入amatro组件
这里写图片描述
修改image的alpha K帧,然后设定这个动画为初始状态,所以这个对象一Awake就开始播放闪烁动画

下面写loadlevel的代码给button,让他被点击时进入下一个level

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class GoToMenu : MonoBehaviour {
    public void OnGoToMenu() {
        Time.timeScale = 0; //暂停依赖时间的组件
        StartCoroutine(GoToTheMenu());
    }

    private IEnumerator GoToTheMenu() {
        yield return null;
        SceneManager.LoadScene("Menu");
    }
}

SceneManager是unity在5.3加的新类取代application.loadlevel,具体自己上官方网站看手册
这里没有直接用loadlevel,而是先暂停了其他组件的运动,虽然我们接下来要做的Menu场景的demo东西不会太多,但以后东西变多了,加载就会变慢,玩家点击屏幕触摸后,把闪烁动画暂停了告诉玩家游戏没死机是更加优美的。添加代码后与button连接

下面我们做Menu场景
这里写图片描述
6个按钮的排布用gird layout自动完成,如果我们不想要被修改大小的话,可以在button上添加一个空的父对象,不过这里我们需要直接并在一起,就不搞空对象了

下面做经验条和体力条,素材是这些,用slider来做
这里写图片描述
首先先对素材进行九宫格处理,因为都有半个像素的过渡,直接拉伸的话会变形,当然你可以直接用填充模式,这里就用两种方法一起处理一下吧
示范做条的地板
这里写图片描述
修改图片的模式,然后拉长他
这里写图片描述
或者在这里划一个缩放九宫格
地板的两头是固定的,下面示范怎么用slider做活动的
这里写图片描述
红圈部分加入的是2个rect transform,默认会建立这两个只有transform的对象,用来控制填充的长短大小,至于里面的图片就是用来控制图像的咯,手柄就一张图不说了,填充条的话和上面一样,九宫格+sliced处理一下。
注意最后勾选掉slider的intertactable,让它不能被玩家拖动,而且把四个颜色全部变为白,不然会变色

最后做一下地图的拖动,可能有插件可以完成这个功能,不过我不知道,所以需要写个脚本,我们先分析下需求
1.玩家可以拖动地图来切换地图
2.我们不想让玩家在拖动时看到地图是拼接在一起的,也就是说地图不会跟随玩家的手势,而是横向幅度到一定程度时(例如>400像素)就切换
3.地图的切换成一个环
4.需要暴露左右切页的方法
5.需要暴露返回当前页数的方法
好,那我们开始吧
我的思路是这样的,首先我们把地图这样拼起来,MAP1作为父,MAP23456(如果有的话)作为子,然后输入这几个数据来定位
这里写图片描述
index代表当前画面显示的是几号地图
count代表总共有多少张地图
960是我们的画布大小,我们的地图大小也被处理成960
speed代表滑动速度
代码如下

using System.Collections;
using System.Collections.Generic;
using UnityEngine.EventSystems;
using UnityEngine;

//继承的三个类分别对应三个拖拽的回调
//虽然我的项目是想发布在安卓平台,但是我对触屏输入那块还不太了解,所以暂时全部当做鼠标点击的方式处理
public class MapDragTool : MonoBehaviour,IBeginDragHandler,IDragHandler,IEndDragHandler {
    public int index = 1;
    public int count = 2;
    public float Canve_X = 960f;
    public float smoothSpeed = 10.0f;

    //dirPos指图片应该移动到的位置
    private Vector2 dirPos;
    //maxLeft代表坐标的最小值,maxright代表最大值
    //如果超出这个范围就意味着我们需要改变坐标让他看起来像个环
    private float MaxLeft;
    private float MaxRight;
    //控制update流程,如果ismoving为真就继续差值滑动图片
    private bool isMoving;
    private float ScreenWidth;
    private float ScreenHeight;
    private Vector2 StartPositon;
    private bool isDrag;

    void Start() {
        Vector2 dirPos = GetComponent<RectTransform>().anchoredPosition;
        //留100像素的误差
        MaxLeft = dirPos.x - ((count - index) * Canve_X) - 100;
        MaxRight = dirPos.x + ((index - 1) * Canve_X) + 100;
        //记录当前屏幕的像素大小
        ScreenWidth = Screen.width;
        ScreenHeight = Screen.height;
        isMoving = false;
    }

    //读取拉动信息
    //isDrag来控制一次完整的拖拽只能翻一页
    public void OnBeginDrag(PointerEventData data) {
        StartPositon = PosFromScreenToCanve(data.position);
        isDrag = true;
    }

    //注意这里要转换坐标,screenwidth和screenheight代表game页面和实际手机上的荧幕大小
    //所以我们得到的点击坐标是基于game和实际荧幕的,需要除以screen再乘以画布大小才是对应的点在画布上的坐标
    private Vector2 PosFromScreenToCanve(Vector2 position) { 
        return (new Vector2(position.x/ScreenWidth*960, position.y/ScreenHeight*540));
    }

    public void OnDrag(PointerEventData data) {
        //得到拖拽位移
        Vector2 DeltaPosition = PosFromScreenToCanve(data.position) - StartPositon;
        if (DeltaPosition.x > 300 && isDrag == true) {
            isMoving = true; isDrag = false;
            LastPage();
        }
        else if (DeltaPosition.x < -400 && isDrag == true) {
            isMoving = true; isDrag = false;
            NextPage();
        }
        CheckIndex();
    }

    public void OnEndDrag(PointerEventData data) {
        isDrag = true;
    }

    void Update() {
        if (isMoving) {
            Vector2 temp = GetComponent<RectTransform>().anchoredPosition;
            //很常见的平缓移动方式,lerp是插值的意思
            temp.x = Mathf.Lerp(temp.x, dirPos.x, Time.deltaTime * smoothSpeed); 
            GetComponent<RectTransform>().anchoredPosition = temp;
            if (temp == dirPos) isMoving = false;
        }
    }

    public void CheckIndex() { 
        //首先判断是否小于maxLeft
        //别忘了设定的100误差
        if (dirPos.x < MaxLeft) {
            Vector2 temp = GetComponent<RectTransform>().anchoredPosition;
            temp.x = (MaxRight-100) + Canve_X;
            GetComponent<RectTransform>().anchoredPosition = temp;
            dirPos.x = (MaxRight - 100);
            index = 1;
        }
        //判断是否大于maxright
        else if (dirPos.x > MaxRight) {
            Vector2 temp = GetComponent<RectTransform>().anchoredPosition;
            temp.x = (MaxLeft + 100) - Canve_X;
            GetComponent<RectTransform>().anchoredPosition = temp;
            dirPos.x = (MaxLeft + 100);
            index = count;
        }
    }

    //暴露翻页接口
    public void NextPage() {
        dirPos.x -= Canve_X;
        index++;
        CheckIndex();
    }

    public void LastPage() {
        dirPos.x += Canve_X;
        index--;
        CheckIndex();
    }
}

Menu界面的功能基本开发完毕了,只剩下一些照猫画虎的UI,如果我做的过程中有新发现的话会补充在下一节开头,下一节应该就是记录做关卡的内容了,灾难的开端啊~~~~

猜你喜欢

转载自blog.csdn.net/keven2148/article/details/78944490
今日推荐