Cocos Creator 3.8.2安卓场景切换旋转时精灵短暂拉伸问题求助
Cocos Creator 3.8.2安卓端场景切换屏幕旋转精灵拉伸问题解决方案
现有实现代码
Cocos Creator 端代码
director.loadScene(this.ReturnGameSceneName(), () => { if (sys.platform === sys.Platform.ANDROID) { native.reflection.callStaticMethod( "com.cocos.game.AppActivity", "ChangeOrientation", "(Z)V", isLandscape ); } if (orientation === macro.ORIENTATION_LANDSCAPE) { view.setDesignResolutionSize(1024, 576, ResolutionPolicy.FIXED_HEIGHT); } else if (orientation === macro.ORIENTATION_PORTRAIT) { view.setDesignResolutionSize(576, 1024, ResolutionPolicy.FIXED_WIDTH); } });
安卓端代码
Activity activity = GlobalObject.getActivity(); if (activity == null) { Log.e("setOrientation", "Activity is null!"); return; } Log.d(TAG, "ChangeOrientation: " + setorientaion); activity.runOnUiThread(new Runnable() { @Override public void run() { if (setorientaion) { activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } else { activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } } });
问题原因
当前实现中,场景加载完成回调里直接触发安卓端屏幕旋转,系统级的屏幕旋转操作完成速度快于Cocos场景内UI元素的布局适配,导致短时间内布局尺寸与屏幕尺寸不匹配,出现精灵拉伸的视觉问题。
解决方案与最佳实践
1. 延迟触发旋转,等待场景布局完成
调整代码执行顺序,先设置Cocos分辨率,再延迟触发安卓端旋转,给场景布局留足时间:
director.loadScene(this.ReturnGameSceneName(), () => { // 优先设置分辨率 if (orientation === macro.ORIENTATION_LANDSCAPE) { view.setDesignResolutionSize(1024, 576, ResolutionPolicy.FIXED_HEIGHT); } else if (orientation === macro.ORIENTATION_PORTRAIT) { view.setDesignResolutionSize(576, 1024, ResolutionPolicy.FIXED_WIDTH); } // 延迟触发安卓端旋转(延迟时间根据场景复杂度调整,100-200ms为合理区间) if (sys.platform === sys.Platform.ANDROID) { setTimeout(() => { native.reflection.callStaticMethod( "com.cocos.game.AppActivity", "ChangeOrientation", "(Z)V", isLandscape ); }, 150); } });
2. 添加全屏遮罩屏蔽拉伸视觉效果
在场景根节点添加全屏纯色遮罩(如黑色),场景加载完成后显示遮罩,直到旋转和布局完全完成后再隐藏:
director.loadScene(this.ReturnGameSceneName(), () => { const maskNode = find("Canvas/ScreenMask"); // 替换为实际遮罩节点路径 if (maskNode) maskNode.active = true; // 先设置分辨率 if (orientation === macro.ORIENTATION_LANDSCAPE) { view.setDesignResolutionSize(1024, 576, ResolutionPolicy.FIXED_HEIGHT); } else if (orientation === macro.ORIENTATION_PORTRAIT) { view.setDesignResolutionSize(576, 1024, ResolutionPolicy.FIXED_WIDTH); } if (sys.platform === sys.Platform.ANDROID) { setTimeout(() => { native.reflection.callStaticMethod( "com.cocos.game.AppActivity", "ChangeOrientation", "(Z)V", isLandscape ); // 旋转完成后再延迟隐藏遮罩,确保系统布局同步 setTimeout(() => { if (maskNode) maskNode.active = false; }, 100); }, 150); } else { setTimeout(() => { if (maskNode) maskNode.active = false; }, 100); } });
3. 安卓端监听旋转完成事件,同步Cocos布局
修改安卓端代码,监听屏幕旋转后的布局变化事件,完成后通知Cocos执行最终布局调整,实现完全同步:
安卓端修改代码
public static void ChangeOrientation(boolean setorientaion) { Activity activity = GlobalObject.getActivity(); if (activity == null) { Log.e("setOrientation", "Activity is null!"); return; } Log.d(TAG, "ChangeOrientation: " + setorientaion); activity.runOnUiThread(new Runnable() { @Override public void run() { activity.setRequestedOrientation(setorientaion ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); // 监听布局变化,确认旋转完成 activity.getWindow().getDecorView().addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { v.removeOnLayoutChangeListener(this); // 移除监听避免重复触发 // 通知Cocos端旋转完成 CocosJavascriptJavaBridge.evalString("window.onOrientationChanged()"); } }); } }); }
Cocos Creator端添加监听
// 在场景脚本的onLoad/start中注册全局监听 window.onOrientationChanged = () => { // 旋转完成后执行分辨率设置与遮罩隐藏 if (orientation === macro.ORIENTATION_LANDSCAPE) { view.setDesignResolutionSize(1024, 576, ResolutionPolicy.FIXED_HEIGHT); } else if (orientation === macro.ORIENTATION_PORTRAIT) { view.setDesignResolutionSize(576, 1024, ResolutionPolicy.FIXED_WIDTH); } const maskNode = find("Canvas/ScreenMask"); if (maskNode) maskNode.active = false; }; director.loadScene(this.ReturnGameSceneName(), () => { const maskNode = find("Canvas/ScreenMask"); if (maskNode) maskNode.active = true; if (sys.platform === sys.Platform.ANDROID) { native.reflection.callStaticMethod( "com.cocos.game.AppActivity", "ChangeOrientation", "(Z)V", isLandscape ); } else { window.onOrientationChanged(); } });
4. 优化分辨率策略配置
确保分辨率策略与旋转方向严格匹配:
- 横屏固定使用
ResolutionPolicy.FIXED_HEIGHT,保证高度适配屏幕,宽度按比例缩放 - 竖屏固定使用
ResolutionPolicy.FIXED_WIDTH,保证宽度适配屏幕,高度按比例缩放 - 可在项目设置中预配置默认分辨率参数,减少动态设置时的冲突
内容的提问来源于stack exchange,提问作者Parv Jain
相关产品推荐
相关产品推荐

