Unity 制作萌系live2d桌宠:屏幕自适应+交互

本文在之前的博客如何使用unity制作萌萌的live2d桌宠的基础上对项目继续改进,解决了屏幕自适应和交互的问题。

先来看看效果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

准备工作

准备工作和环境配置在上一篇博客已介绍,这里不再赘述。但还要提一点的是项目仍在 unity2018.4.24.f1(很重要) 的环境下开发(unity2019无法正常工作,其他版本未测试),操作系统为Windows。

使用unity显示live2d人物

上篇博客介绍过,这里简单说一下流程:

  • 下载Live2D_SDK_Unity_2.1.04_2_jp,将里面的文件拷贝到unity的目录,然后导入Live2DFrameworkNeeds包
  • 将live2d素材放入unity目录中的Resources文件夹
  • 新建一个空对象用于显示人物,取名为haru(名字随意)
  • 为空对象添加Mesh Filter、MeshCllider、L App Model Proxy、My Game Controller和Audio Source,相关参数参考上篇博客。

运行程序应该有下面的效果
在这里插入图片描述

全屏+背景透明+点击穿透+置顶

导出程序的时候必须使背景透明,否则就谈不上桌宠了。这里直接给出背景透明+点击穿透的代码,将此代码拖动到一个空对象上,然后把相机的Clear Flags设为Solid Color,并把背景颜色调成黑色。(代码基于这篇博客修改

using UnityEngine;
using System;
using System.Runtime.InteropServices;

public class TablePetBackSample : MonoBehaviour
{
    public string strProduct;//项目名称
    private int currentX;
    private int currentY;
    #region Win函数常量
    private struct MARGINS
    {
        public int cxLeftWidth;
        public int cxRightWidth;
        public int cyTopHeight;
        public int cyBottomHeight;
    }
    [DllImport("user32.dll")]
    private static extern IntPtr GetActiveWindow();

    [DllImport("user32.dll")]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    [DllImport("user32.dll")]
    static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

    [DllImport("user32.dll")]
    static extern int GetWindowLong(IntPtr hWnd, int nIndex);

    [DllImport("user32.dll")]
    static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);

    [DllImport("user32.dll")]
    static extern int SetLayeredWindowAttributes(IntPtr hwnd, int crKey, int bAlpha, int dwFlags);

    [DllImport("Dwmapi.dll")]
    static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);
    [DllImport("user32.dll")]
    private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
    //private const int WS_POPUP = 0x800000;
    private const int GWL_EXSTYLE = -20;
    private const int GWL_STYLE = -16;
    private const int WS_EX_LAYERED = 0x00080000;
    private const int WS_BORDER = 0x00800000;
    private const int WS_CAPTION = 0x00C00000;
    private const int SWP_SHOWWINDOW = 0x0040;
    private const int LWA_COLORKEY = 0x00000001;
    private const int LWA_ALPHA = 0x00000002;
    private const int WS_EX_TRANSPARENT = 0x20;
    #endregion
    
    IntPtr hwnd;
    void Awake()
    {

#if UNITY_EDITOR
        print("unity内运行程序");
#else
        hwnd = FindWindow(null, strProduct);
        int intExTemp = GetWindowLong(hwnd, GWL_EXSTYLE);
        SetWindowLong(hwnd, GWL_EXSTYLE, intExTemp | WS_EX_TRANSPARENT | WS_EX_LAYERED);
        SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_BORDER & ~WS_CAPTION);
        currentX = 0;
        currentY = 0;
        SetWindowPos(hwnd, -1, currentX, currentY, Screen.currentResolution.width, Screen.currentResolution.height, SWP_SHOWWINDOW);
        var margins = new MARGINS() { cxLeftWidth = -1 };
        DwmExtendFrameIntoClientArea(hwnd, ref margins);     
#endif
    }
}

相机参数:
在这里插入图片描述

注意代码中strProduct一定要与Inspector种的Product Name一致,否则会出现奇怪的Bug(很重要,可能会影响unity导出的同名程序使用)。
在这里插入图片描述
效果如下:
在这里插入图片描述
可以看到背景是透明的,而且不妨碍鼠标网页的交互。

屏幕自适应

桌宠不能挡在中间影响我们正常使用电脑,我们需要让她处于右下角的位置并适应屏幕分辨率。首先我们需要把相机的Projection调整为Orthographic,
在这里插入图片描述
然后编写可以根据屏幕分辨率动态的调整桌宠的大小和位置的代码。代码如下,把代码拖到有live2d组件的对象上(即haru上)就可。

using UnityEngine;

public class RolePositionControl : MonoBehaviour
{
    float rolewidth = 520;
    float roleheight = 520;
    private GameObject MainCamera;
    // Start is called before the first frame update
    void Start()
    {
        MainCamera = GameObject.Find("Main Camera");
    }

    // Update is called once per frame
    void Update()
    {
        //保持角色的大小和位置
        float frustumHeight = MainCamera.GetComponent<Camera>().orthographicSize * 2;
        float frustumWidth = frustumHeight * MainCamera.GetComponent<Camera>().aspect;
        float rolewidth = GetComponent<MeshFilter>().mesh.bounds.size.x;
        float roleheight = GetComponent<MeshFilter>().mesh.bounds.size.x;
        transform.localPosition = new Vector3((frustumWidth - rolewidth) / 2, -(frustumHeight - roleheight) / 2, transform.localPosition.z);
    }
}

效果如下:
在这里插入图片描述

交互

现在我们的桌宠只能看不能摸,也不会发出声音,下面我们来编写一些交互的代码。本人不熟悉unity的live2d编程,所以直接参照live2d框架中My Game Controller进行简单的改写。代码如下,为了不影响原来的包可以新建一个自己的My Game Controller组件(此处我命名为GameControl_X ),然后替换替换haru上的My Game Controller。

为何要改写My Game Controller?
原先的My Game Controller通过Input.GetMouseButton等接口获取鼠标状态,这样的方法在本项目中是无效的,前面的点击穿透功能会使程序无法检测到鼠标按下。所以这里需要使用windows接口来监测鼠标是否按下。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.InteropServices;
public class GameControl_X: MonoBehaviour
{
    private static LAppLive2DManager instance;
    private float lastX = -1;
    private float lastY = -1;
    private GameObject MainCamera;
    //Windows接口
    [DllImport("user32.dll")]
    public static extern short GetAsyncKeyState(int vKey);
    private const int VK_LBUTTON = 0x01; //鼠标左键
    private const int VK_RBUTTON = 0x02; //鼠标右键

    //动画辅助key
    string AniKey = "Begin";

    // Start is called before the first frame update
    void Awake()
    {
        MainCamera = GameObject.Find("Main Camera");
        if (MainCamera != null)
        {
            if (MainCamera.GetComponent<Camera>().orthographic)
            {
                LAppLive2DManager.Instance.SetTouchMode2D(true);

            }
            else
            {
                Debug.Log("\"Main Camera\" Projection : Perspective");

                LAppLive2DManager.Instance.SetTouchMode2D(false);
            }
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (GetAsyncKeyState(VK_LBUTTON) != 0)
        {
            if (AniKey == "Begin")
            {
                lastX = Input.mousePosition.x;
                lastY = Input.mousePosition.y;

                LAppLive2DManager.Instance.TouchesBegan(Input.mousePosition);
                AniKey = "Ani";
            }
            else
            {
                if (lastX == Input.mousePosition.x && lastY == Input.mousePosition.y)
                {
                    return;
                }
                lastX = Input.mousePosition.x;
                lastY = Input.mousePosition.y;
                LAppLive2DManager.Instance.TouchesMoved(Input.mousePosition);
                AniKey = "Begin";
            }
        }
        else
        {
            if (AniKey == "Ani")
            {
                lastX = -1;
                lastY = -1;
                LAppLive2DManager.Instance.TouchesEnded(Input.mousePosition);
                AniKey = "Begin";
            }

        }
    }
}

效果如下,鼠标按下后haru会看向鼠标的位置,也可以做点击、摸头等交互。
在这里插入图片描述


到此大功告成,懂live2d的同学还可以将haru替换成自己喜欢的萌物。

Box2D和Cocos2D是两个游戏开发框架。Box2D是一个用于物理模拟的开源库,可以模拟刚体的运动和碰撞等物理效果。Cocos2D是一个用于2D游戏开发的跨平台框架,提供了丰富的图形渲染和用户交互功能。\[1\] 在使用Cocos2D和Box2D进行游戏开发时,你可以利用Box2D来处理游戏中的物理效果,比如重力、碰撞和刚体运动等。Cocos2D提供了与Box2D的集成,使得开发者可以方便地在Cocos2D中使用Box2D的功能。你可以通过创建物理世界、添加刚体和设置碰撞检测等来实现游戏中的物理效果。\[2\] 如果你刚刚接触Cocos2D和Box2D,建议你先学习Cocos2D和Box2D的基础知识,然后再深入学习如何在Cocos2D中使用Box2D。你可以参考一些入门教程,比如《Cocos2D入门》和《Box2D入门》。如果你对OpenGL ES 2.0和自定义Cocos2D 2.X着色器等背景知识感到困惑,你可以查阅相关教程来获取更多的帮助。\[3\] #### 引用[.reference_title] - *1* *3* [如何使用Box2D和Cocos2D制作一款像Fruit Ninja一样的游戏-第1部分](https://blog.csdn.net/kaka626/article/details/9397825)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [用Box2D和cocos2d-x制作弹弓类游戏](https://blog.csdn.net/qq55008307/article/details/8090839)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值