unity 输入法遮挡解决方案

前言
1>聊天软件中,虚拟键盘弹起会盖住聊天窗口,将整个聊天界面上移
2>unity游戏中, 虚拟键盘弹起会盖住输入框,将输入框 上移(不能跟聊天软件一样处理)

这章讲述 游戏解决方案

1 环境
unity2020

2 布局

在这里插入图片描述
3 脚本
SampleScene.cs
拖到Main Camera 上 再把InputField 拖到脚本变量里
在这里插入图片描述

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

public class SampleScene : MonoBehaviour
{
	public InputField inputField;
    Canvas canvas;
    ChatViewAdaptMobileKeyBoard chatview;
    GameObject canvasobject;
    // Start is called before the first frame update
    void Start()
    {
        Debug.LogError("SampleScene Start 1");
        canvas = (Canvas) GameObject.FindObjectOfType(typeof(Canvas));
        if(canvas == null)
        {
            Debug.LogError("SampleScene Start error");
        }
        canvasobject = canvas.gameObject;

        Debug.LogError("SampleScene Start 3");
        chatview = ChatViewAdaptMobileKeyBoard.Create(canvasobject, inputField);
        Debug.LogError("SampleScene Start 4");

    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

ChatViewAdaptMobileKeyBoard.cs

using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 移动设备输入框的自适应组件
/// </summary>
public class ChatViewAdaptMobileKeyBoard : MonoBehaviour {
    public InputField _inputField;
   // static ChatViewAdaptMobileKeyBoard instance = null;

    /// <summary>
    /// 自适应(弹出输入框后整体抬高)的面板的初始位置
    /// </summary>
    private Vector2 _adaptPanelOriginPos;
    private RectTransform _adaptPanelRt;
    private float RESOULUTION_HEIGHT = 0 ;;//1080F; //1280F;
    private float lastkeyboardHeight = 0.00f;
    private float rtx = 0;
    private float rty = 0;

    public static ChatViewAdaptMobileKeyBoard Create(GameObject attachRoot, InputField inputField) {
        ChatViewAdaptMobileKeyBoard instance = null;
        instance = attachRoot.AddComponent<ChatViewAdaptMobileKeyBoard>();
        instance._inputField = inputField;
        return instance;
    }

    private void Start() {
        RESOULUTION_HEIGHT =  Display.main.systemHeight ; //屏幕高
        Debug.LogError("检测到InputField ChatViewAdaptMobileKeyBoard.start()");
        _inputField.onEndEdit.AddListener(OnEndEdit);
        _inputField.onValueChanged.AddListener(OnValueChanged);
        //   _adaptPanelRt = transform.Find("TabControl/Panels").GetComponent<RectTransform>(); 
        //  _adaptPanelRt = transform.Find("Canvas/InputField").GetComponent<RectTransform>();
        _adaptPanelRt = this._inputField.GetComponent<RectTransform>();//相对于父对象的位置(没有父对象就根据世界原点)
     //   rtx = _adaptPanelRt.
       _adaptPanelOriginPos = _adaptPanelRt.anchoredPosition; //自身中心点相对于锚点之间的位置
        rtx = _adaptPanelOriginPos.x;
        rty = _adaptPanelOriginPos.y;
        Debug.LogError("检测到InputField inputfield org x =" + _adaptPanelOriginPos.x.ToString() + " y="+ _adaptPanelOriginPos.y.ToString());
    }

    private void Update() {
        if (_inputField.isFocused) {

            if (Application.platform == RuntimePlatform.Android) {
                float keyboardHeight = (int)(AndroidGetKeyboardHeight()*RESOULUTION_HEIGHT)/Screen.height;
                if (keyboardHeight - lastkeyboardHeight < 1.1f || keyboardHeight - lastkeyboardHeight < -1.1f)
                {

                }
                else
                {

                    lastkeyboardHeight = keyboardHeight;
                    //  Debug.LogFormat("安卓平台检测到InputField.isFocused为真,获取键盘高度:{0}, Screen.height:{1}", keyboardHeight, Screen.height);
                    //2340 × 1080像素  mate30
                    //  Debug.LogError("安卓平台检测到InputField.isFocused为真,获取键盘高度:"+ keyboardHeight.ToString()+" Screen.height:"+ Screen.height.ToString());
                    //_adaptPanelRt.anchoredPosition = Vector3.up * (keyboardHeight);
                    //  _adaptPanelRt.anchoredPosition = _adaptPanelOriginPos.Set(_adaptPanelOriginPos.x,_adaptPanelOriginPos.y);
                    _adaptPanelRt.anchoredPosition = new Vector2(rtx, rty + keyboardHeight);// +150f);//150 输入法的输入框 高度(估计的)//勾选 hide mobile intput 不需要额外增加150
                    _adaptPanelRt.ForceUpdateRectTransforms();  //强制更新

                    Debug.LogError("安卓平台检测到InputField.isFocused为真,获取键盘高度:" + keyboardHeight.ToString() + " Screen.height:" + Screen.height.ToString() + " anchposy=" + _adaptPanelRt.anchoredPosition.y.ToString());
                }
            }
            else if (Application.platform == RuntimePlatform.IPhonePlayer) {
                 float keyboardHeight = IOSGetKeyboardHeight() * RESOULUTION_HEIGHT / Screen.height;   
              //   Debuger.LogFormat("IOS平台检测到键盘高度:{0},Screen.height: {1}", keyboardHeight, Screen.height);
                _adaptPanelRt.anchoredPosition = Vector3.up * keyboardHeight;
            }
            else {
                //Editor或其他平台,测试用!

                // _adaptPanelRt.anchoredPosition = Vector3.up * 300f;
                //  _adaptPanelRt.anchoredPosition = Vector2.up * 300f;
                Debug.LogError("安卓平台检测到InputField.isFocused为真,获取键盘高度 other 提升300f");

               _adaptPanelRt.anchoredPosition = new Vector2(rtx, rty + 300f); //.Set(rtx, rty + 300f);
            }
        }else
        {
            if (Application.platform == RuntimePlatform.Android)
            {
                if ((int)_adaptPanelRt.anchoredPosition.y -(int)rty < 1.1f || (int)_adaptPanelRt.anchoredPosition.y - (int)rty < -1.1f)
                {

                }
                else
                {
                    Debug.LogError("安卓平台检测到InputField.isFocused为假,获取键盘高度 y=" + rty.ToString());
                    // _adaptPanelRt.anchoredPosition = _adaptPanelOriginPos; //自身中心点相对于锚点之间的位置
                    _adaptPanelRt.anchoredPosition = new Vector2(rtx, rty);

                }
                    
            }
           
        }
    }

    private void OnValueChanged(string arg0) { }


    /// <summary>
    /// 结束编辑事件,TouchScreenKeyboard.isFocused为false的时候
    /// </summary>
    /// <param name="currentInputString"></param>
    private void OnEndEdit(string currentInputString) {
        //Debuger.LogFormat("OnEndEdit, 输入内容:{0}, 结束时间:{1}", currentInputString, Time.realtimeSinceStartup);
        // _adaptPanelRt.anchoredPosition = _adaptPanelOriginPos;
        Debug.LogError("安卓平台检测到InputField.isFocused 结束,获取键盘高度 y=" + rty.ToString());
        // _adaptPanelRt.anchoredPosition.Set(rtx, rty);
        _adaptPanelRt.anchoredPosition = new Vector2(rtx, rty);
        lastkeyboardHeight = 0.0f;
        _adaptPanelRt.ForceUpdateRectTransforms();  //强制更新
    }

    /// <summary>
    /// 获取安卓平台上键盘的高度
    /// </summary>
    /// <returns></returns>
    public int AndroidGetKeyboardHeight() {
        using (AndroidJavaClass UnityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) {
            AndroidJavaObject View = UnityClass.GetStatic<AndroidJavaObject>("currentActivity").
                Get<AndroidJavaObject>("mUnityPlayer").Call<AndroidJavaObject>("getView");

            using (AndroidJavaObject Rct = new AndroidJavaObject("android.graphics.Rect")) {
                View.Call("getWindowVisibleDisplayFrame", Rct);
                return Screen.height - Rct.Call<int>("height");
            }
        }
    }


    public float IOSGetKeyboardHeight() {
        return TouchScreenKeyboard.area.height;
    }
}

4 运行结果
注意 inputfield hidemobileinput 勾选 不然 会多出个输入框
在这里插入图片描述

5 后续如需可以上传DEMO工程

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Unity实时遮挡剔除是一种用于性能优化的技术,通过在渲染场景时动态地检测和移除被其他物体遮挡的不可见物体,提高渲染效率和帧率。 实时遮挡剔除的原理是通过摄像机的视锥体来确定被剔除的物体,只有在视锥体内的物体才被渲染,而视锥体外的物体则被剔除。这样可以避免不可见物体的渲染,减少对GPU、CPU和带宽的压力,提高游戏的性能和流畅度。 Unity实时遮挡剔除的步骤主要包括: 1. 确定摄像机的视锥体,即摄像机能够看到的范围。 2. 对于每个物体,判断其是否在视锥体内。如果在视锥体外,就剔除它。 3. 如果物体在视锥体内,继续检测是否被其他物体遮挡。如果被遮挡,也将其剔除。 4. 对剩下的可见物体进行渲染。 Unity实时遮挡剔除有助于提高游戏的渲染性能,尤其是在大型场景或者复杂的游戏世界中。它可以减少渲染物体的数量,加快渲染速度,使游戏更加流畅。此外,通过合理的遮挡剔除设置,还可以减少GPU和CPU的负担,让游戏在更低的硬件要求下运行。 总之,Unity实时遮挡剔除是一种重要的性能优化技术,能够提高游戏的渲染效率和帧率,为玩家提供更好的游戏体验。 ### 回答2: Unity实时遮挡剔除(Real-time Occlusion Culling)是一种用于提高游戏性能的技术,旨在减少对不可见物体的绘制。在游戏场景中,有些物体可能被其他物体遮挡,这些被遮挡的物体在渲染时不需要显示,因此可以将其剔除,从而节约计算资源。 Unity实时遮挡剔除的实现原理是通过预先计算场景中不同物体的可见性。首先,进行场景的静态分析,生成一张场景中所有物体的可见性图(Occlusion Map),记录每个点是否可见。接下来,通过相机的视锥体(视野范围),对于视锥体内的物体,通过检查其在可见性图中的位置来判断其可见性。如果物体被视锥体外的其他物体遮挡,那么它将被剔除,否则将进行渲染。 通过使用Unity实时遮挡剔除,我们可以提高游戏的渲染效率,减少不必要的绘制操作,从而改善游戏的性能和流畅度。这对于那些需要处理大量复杂场景的游戏特别有用,因为它可以在运行时动态地确定哪些物体需要渲染,减轻了GPU和CPU的负担,使游戏更加流畅。 Unity实时遮挡剔除虽然对场景的可见性进行了优化,但也有一些限制。例如,在动态物体或需要频繁更新的场景中,无法准确地预计可见性,因此需要使用其他技术进行补充,如级别细化(LOD)和动态批处理等。 综上所述,Unity实时遮挡剔除是一种采用预先计算可见性的技术,旨在提高游戏性能。通过剔除不可见的对象,减少了对它们的渲染,使游戏在复杂场景下运行更加流畅。 ### 回答3: Unity的实时遮挡剔除是一种技术,可以在场景中动态隐藏不可见的物体,从而提高渲染的效率。这个技术可以有效地避免不必要的渲染,减少GPU的负担,从而提高游戏性能。 在Unity中,实时遮挡剔除是通过一个叫做视锥裁剪器(Frustum Culling)的技术来实现的。视锥裁剪器实际上是一个虚拟的摄像机,它只渲染在视锥体内的物体。通过将在视锥体外的物体从渲染队列中剔除掉,可以减少不必要的渲染操作,提高渲染效率。 Unity的实时遮挡剔除还使用了一种叫做遮挡剔除(Occlusion Culling)的技术。遮挡剔除是通过判断一个物体是否被其他物体遮挡住来进行的。当一个物体被其他物体遮挡住时,该物体的渲染操作就被剔除掉,从而减少不必要的渲染。 Unity的实时遮挡剔除在编辑器中可以通过配置设置来应用。通过在场景中添加遮挡剔除区域,可以指定哪些物体应该被剔除。而且,Unity还提供了一些调试工具,可以帮助开发者进行优化,如场景的可视化遮挡剔除图和性能分析器。 总之,Unity的实时遮挡剔除是一种有效的渲染优化技术,可以提高游戏性能,减少不必要的渲染。通过视锥裁剪器和遮挡剔除的配合使用,可以在保证画面质量的同时提高游戏的帧率和流畅度。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值