简简单单使用Unity打包项目到安卓平台(二)

  • 1.输入
  • 2.Roll a ball
  • 2.1.导入
  • 2.2.修改
  • 3.扩展
  • 3.1.画面
  • 3.2.更多设置
  • 3.3.摇杆的位置



1.输入

Unity给了移动端输入的API,比如触摸、加速度计的输入,也可以调用手机的震动反馈。

详见:Android 移动端脚本移动设备输入InputHandheld 等。

当然我们可以用这些API写我们自己的输入方式,但是我现在想要用一个虚拟摇杆来控制roll a ball中小球的移动。自己写一个有点麻烦,搜了一下商店里的都是收费的。幸好在github上找到一个符合预期的项目 Unity3D-Simple-Mobile-Joystick

下载下来之后有一个package,导入package,demo和demo相关的就不需要导入了。只要下图中勾选的内容。

unity 打包查看unity default resources unity打包项目_unity3d


接下来把MobileJoyStick预制体放置到场景中,因为我不需要右摇杆,就把RightJoyStick给禁用掉了。效果如下图所示。并且右键->UI->EventSystem新建一个EventSystem,否则无法拖动摇杆。

unity 打包查看unity default resources unity打包项目_ide_02


并且把LeftJoyStick的锚点改成左下角,确保UI的位置保持在屏幕左下角。

unity 打包查看unity default resources unity打包项目_unity_03


接下来稍微写点东西测试测试一下,看看能不能用。

using UnityEngine;
using UnityEngine.UI;

public class MyInputTest : MonoBehaviour
{
    // 摇杆
    public MobileInputController controller;

    // UI
    public Text horiText;
    public Text vertText;

    private void Update()
    {
        horiText.text = "Hori:" + controller.Horizontal;
        vertText.text = "Vert:" + controller.Vertical;
    }
}

unity 打包查看unity default resources unity打包项目_ide_04


没有问题。

2.Roll a ball

2.1.导入

直接去商店下 成品 ,我可懒得重新写了。

导入roll a ball的完整项目。(ProjectSettings我就不导了,我怕把我之前的一些设置给覆盖了,问题应该不大)

unity 打包查看unity default resources unity打包项目_unity3d_05


导入完成之后打开Roll-a-ball场景,运行一下没有问题。

2.2.修改

然后现在把他改成用虚拟摇杆输入。首先把MobileJoyStick预制体放入Roll-a-ball场景,这里已经有EventSystem就不用再加了。
然后打开PlayerController.cs这个脚本进行一些修改,修改后如下。(原来的所有注释都删掉了,不难。现在注释的都是修改或添加的地方)

using UnityEngine;
using UnityEngine.UI;

public class PlayerController : MonoBehaviour {

	// 虚拟摇杆
	public MobileInputController joystick;

	public float speed;
	public Text countText;
	public Text winText;

	private Rigidbody rb;
	private int count;

	void Start ()
	{
		rb = GetComponent<Rigidbody>();
		count = 0;
		SetCountText ();
		winText.text = "";

		// 屏幕旋转 设置为跟随设备的旋转
		Screen.orientation = ScreenOrientation.AutoRotation;
	}

	void FixedUpdate ()
	{
        // 修改前
        //float moveHorizontal = Input.GetAxis ("Horizontal");
        //float moveVertical = Input.GetAxis ("Vertical");

        // 修改后
        float moveHorizontal = joystick.Horizontal;
        float moveVertical = joystick.Vertical;

        Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);

		rb.AddForce (movement * speed);
	}

	void OnTriggerEnter(Collider other) 
	{
		if (other.gameObject.CompareTag ("Pick Up"))
		{
			// 只有在安卓平台才震动
#if UNITY_ANDROID
			// 震动 只能震动0.5s
			Handheld.Vibrate();
#endif
			other.gameObject.SetActive (false);
			count = count + 1;
			SetCountText ();
		}
	}

	void SetCountText()
	{
		countText.text = "Count: " + count.ToString ();
		if (count >= 12) 
		{
			winText.text = "You Win!";
		}
	}
}

然后记得在编辑器内给public MobileInputController joystick赋值。然后按上面的方法,把Scenes In Build改成当前场景然后打包出来在手机上运行。
效果如视频所示,手机上播放可能看到的视频不对,可以到原视频观看。

震动的话,Unity的API只给了Handheld.Vibrate()这一个函数,也没有设置震动时间的。感觉这个时间太长了。但是查了一下发现要修改震动时间还得重新打包SDK,算了下次吧。参考自《Unity3D —— 手机设备震动接口》《Unity+Android交互教程——让手机"动"起来》。

3.扩展

虽然项目已经成功的打包并运行了,但是还有一些地方是可以完善的。

3.1.画面

unity 打包查看unity default resources unity打包项目_ide_06


这是在手机上运行的截图,可以看出来远处的方块没有阴影了。但是在Unity编辑器中看是好好的。

要解决这个,就打开编辑器中的Editor->ProjectSetting->Quality

unity 打包查看unity default resources unity打包项目_android_07


可以看到这里Unity给我们预先设置了6个等级的质量选项,这里默认PC平台是最高质量,安卓平台是中等质量(当然这里有几个等级,默认是什么等级,每个等级的具体设置是什么都是可以自行修改的) 。

unity 打包查看unity default resources unity打包项目_unity3d_08


选择Medium可见,这一等级的阴影距离只有20,而最高等级的Ultra有150。这就是问题所在,阴影距离太近了。

我们可以把Medium的阴影距离改大,也可以把安卓的默认等级调为Ultra。我这就直接调成Ultra好了,这么简单的一个场景手机还是撑得住的。

3.2.更多设置

如果刚才留意过的话,我们会发现我们每一次导出的安卓应用图标和名称都是这个。

unity 打包查看unity default resources unity打包项目_unity_09


可以修改吗?当然可以。

打开Editor->ProjectSetting->Player,就可以看到这样一个界面。在这里可以修改我们的公司姓名、应用的名称、版本号和图标等等。

详情可见Android Player 设置,根据自己的需求进行设置即可。

unity 打包查看unity default resources unity打包项目_android_10

3.3.摇杆的位置

实际运行的过程中(可看前面的演示视频),可以看出虚拟摇杆的位置移动的太小了,根本移不到遥感背景的边缘。在编辑器中是可以的。研究了一通发现是分辨率有关系,因为这一个虚拟遥感的插件计算遥感的位置的时候,对手机的分辨率有一定的需求。涉及到一些UI适配的问题,没有深究。
稍微改了一下代码就解决了。打开MobileInputController.cs文件(前面github上下的那个插件中的脚本) ,改成下面代码的让子,然后记得给CanvasScaler赋值为这样就解决了。(其实现在这种方式,当手机的长宽比例变化太大的时候还是会出问题,我不想改了)

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

[RequireComponent(typeof(AspectRatioFitter))]
public class MobileInputController : MonoBehaviour, IDragHandler, IEndDragHandler, IPointerDownHandler, IPointerUpHandler {

    public RectTransform Background;
    public RectTransform Knob;
    [Header("Input Values")]
    public float Horizontal = 0;
    public float Vertical = 0;

    Vector2 PointPosition;

    public CanvasScaler canvasScaler;
    private Vector2 insideWidth; // 摇杆背景和摇杆的内部宽度差
    private Vector2 canvasScale; // 参考分辨率与实际分辨率的比例

    public void OnDrag(PointerEventData eventData)
    {
        PointPosition = new Vector2(
            (eventData.position.x - Background.position.x) / insideWidth.x * canvasScale.x,
            (eventData.position.y - Background.position.y) / insideWidth.y * canvasScale.y);

        PointPosition = (PointPosition.magnitude>1.0f)?PointPosition.normalized :PointPosition;

        Knob.anchoredPosition = new Vector2
            (PointPosition.x * insideWidth.x,
            PointPosition.y * insideWidth.y);
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        PointPosition = new Vector2(0f,0f);
        Knob.transform.position = Background.position;
    }
    public void OnPointerDown(PointerEventData eventData)
    {
        // 计算摇杆背景和摇杆的内部宽度差
        insideWidth.x = (Background.rect.size.x - Knob.rect.size.x) / 2;
        insideWidth.y = (Background.rect.size.y - Knob.rect.size.y) / 2;

        // 计算参考分辨率与实际分辨率的比例
        canvasScale.x = canvasScaler.referenceResolution.x / Screen.currentResolution.width;
        canvasScale.y = canvasScaler.referenceResolution.y / Screen.currentResolution.height;

        OnDrag(eventData);
    }

    public void OnPointerUp(PointerEventData eventData) {
        OnEndDrag(eventData);
    }
   
	void Update () {
        Horizontal = PointPosition.x;
        Vertical = PointPosition.y;
    }

    public Vector2 Coordinate()
    {
        return new Vector2(Horizontal,Vertical);
    }
}

记得把ReferenceResolution改成和手机分辨率一样的或者比例一样的。

unity 打包查看unity default resources unity打包项目_android_11

(roll a ball告一段落,下一步是尝试AR)
(还有就是,可以把上面脚本中Screen.orientation = ScreenOrientation.AutoRotation;删掉,直接在projectSetting->player中把orientation默认设置为横屏)