当前位置: 首页 > news >正文

Unity3D仿星露谷物语开发17之空库存栏UI

1、目标

将库存栏放在游戏界面中,一般情况下角色居中展示时库存栏在底部,当角色位于界面下方时库存栏展示在顶部避免遮挡。

2、CanvasGroup组件

用于集中控制UI元素的透明度、交互性和射线投射行为。CanvasGroup的Alpha属性允许渐变效果,Interactable决定元素是否可交互,BlocksRaycasts影响图形射线检测,而IgnoreParentGroups选项则控制是否忽略父对象的CanvasGroup设置。这些特性在创建互动游戏场景时尤为有用。

3、Aspect Ratio Fitter组件

Aspect Ratio Fitter 组件的核心作用是按照给定的宽高比调整 UI 元素的尺寸。它可以根据宽度调整高度,也可以根据高度调整宽度,从而确保 UI 元素的宽高比始终固定,不会因为外部布局的变化而拉伸或压缩。

它有以下几种模式:

  • None:不做任何宽高比调整,元素保持原始尺寸。
  • Width Controls Height:根据宽度来调整高度,确保元素的宽高比保持不变。
  • Height Controls Width:根据高度来调整宽度,以确保比例正确。
  • Fit In Parent:在父容器内缩放元素,保持宽高比不变,同时确保元素的大小适合父容器。
  • Envelope Parent:让元素包裹住父容器,保持比例,同时元素可能会超过父容器的边界。

这个属性用于设置 UI 元素的目标宽高比。通常,宽高比是通过 宽度 / 高度 的形式表示。例如,如果想保持 16:9 的比例,则需要将 Aspect Ratio 设置为 16 / 9

4、创建UI

在Hierarchy -> PersistentScene中创建空对象命名为UI。

在UI下创建Canvas命名为MainGameUICanvas。Canvas是UI组件的容器。相关属性设置如下:

在MainGameUICanvas下创建空物体命名为UICanvasGroup,添加两个组件Canvas Group和Aspect Ratio Fitter。

在UICanvasGroup下创建空物体命名为UIInventoryBar。

添加Image组件,并设置下列属性。

对于位置信息,按Shift + Alt键选中中间底部,此时Pos X/Y/Z均为0,修改Pos Y为2.5。

(Shift -> Shift + Alt键)

效果如下:

5、编写脚本

在Assets -> Scripts下新增UI目录,同时新增UIInventory子目录,在此目录下新增UIInventorybar.cs脚本。

(1)优化Player类

首先,我们需要根据角色的位置判断bar到底是处于底部还是顶部,所以Player类需要对外提供坐标信息,而且是相对屏幕的坐标。

修改Player.cs如下:

private Camera mainCamera;mainCamera = Camera.main;public Vector3 GetPlayerViewportPosition()
{// Vector3 viewport position for player (0,0) viewport bottom left, (1,1) viewport top rightreturn mainCamera.WorldToViewportPoint(gameObject.transform.position);
}

此时Player.cs完整代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : SingletonMonobehaviour<Player>
{private float xInput;private float yInput;private bool isWalking;private bool isRunning;private bool isIdle;private bool isCarrying = false;private ToolEffect toolEffect = ToolEffect.none;private bool isUsingToolRight;private bool isUsingToolLeft;private bool isUsingToolUp;private bool isUsingToolDown;private bool isLiftingToolRight;private bool isLiftingToolLeft;private bool isLiftingToolUp;private bool isLiftingToolDown;private bool isPickingRight;private bool isPickingLeft;private bool isPickingUp;private bool isPickingDown;private bool isSwingToolRight;private bool isSwingToolLeft;private bool isSwingToolUp;private bool isSwingToolDown;private Camera mainCamera;private Rigidbody2D rigidbody2D;private Direction playerDirection;private float movementSpeed;private bool _playerInputIsDisabled = false;public bool PlayerInputIsDisabled { get => _playerInputIsDisabled; set => _playerInputIsDisabled = value; }protected override void Awake(){base.Awake();rigidbody2D = GetComponent<Rigidbody2D>();mainCamera = Camera.main;}private void Update(){#region  Player InputResetAnimationTrigger();PlayerMovementInput();PlayerWalkInput();// Send event to any listeners for player movement inputEventHandler.CallMovementEvent(xInput, yInput, isWalking, isRunning, isIdle, isCarrying, toolEffect,isUsingToolRight, isUsingToolLeft, isUsingToolUp, isUsingToolDown,isLiftingToolRight, isLiftingToolLeft, isLiftingToolUp, isLiftingToolDown,isPickingRight, isPickingLeft, isPickingUp, isPickingDown,isSwingToolRight, isSwingToolLeft, isSwingToolUp, isSwingToolDown,false, false, false, false);#endregion}private void FixedUpdate(){PlayerMovement();}private void PlayerMovement(){Vector2 move = new Vector2(xInput * movementSpeed * Time.deltaTime, yInput * movementSpeed * Time.deltaTime);rigidbody2D.MovePosition(rigidbody2D.position + move);}private void ResetAnimationTrigger(){toolEffect = ToolEffect.none;isUsingToolRight = false;isUsingToolLeft = false;isUsingToolUp = false;isUsingToolDown = false;isLiftingToolRight = false;isLiftingToolLeft = false;isLiftingToolUp = false;isLiftingToolDown = false;isPickingRight = false;isPickingLeft = false;isPickingUp = false;isPickingDown = false;isSwingToolRight = false;isSwingToolLeft = false;isSwingToolUp = false;isSwingToolDown = false;}private void PlayerMovementInput(){xInput = Input.GetAxisRaw("Horizontal");yInput = Input.GetAxisRaw("Vertical");// 斜着移动if (xInput != 0 && yInput != 0) {xInput = xInput * 0.71f;yInput = yInput * 0.71f;}// 在移动if (xInput != 0 || yInput != 0) {isRunning = true;isWalking = false;isIdle = false;movementSpeed = Settings.runningSpeed;// Capture player direction for save gameif (xInput < 0){playerDirection = Direction.left;}else if (xInput > 0){playerDirection = Direction.right;}else if (yInput < 0){playerDirection = Direction.down;}else{playerDirection = Direction.up;}}else if(xInput == 0 && yInput == 0){isRunning = false;isWalking = false;isIdle = true;}}// 按住Shift键移动为walkprivate void PlayerWalkInput(){if(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)){isRunning = false;isWalking = true;isIdle = false;movementSpeed = Settings.walkingSpeed;}else{isRunning = true;isWalking = false;isIdle = false;movementSpeed = Settings.runningSpeed;}}public Vector3 GetPlayerViewportPosition(){// Vector3 viewport position for player (0,0) viewport bottom left, (1,1) viewport top rightreturn mainCamera.WorldToViewportPoint(gameObject.transform.position);}
}

(2)编写UIInventorybar类

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class UIInventoryBar : MonoBehaviour
{private RectTransform rectTransform;private bool _isInventoryBarPositionBottom = true;public bool IsInventoryBarPositionBottom { get { return _isInventoryBarPositionBottom;} set { _isInventoryBarPositionBottom = value; } }private void Awake(){rectTransform = GetComponent<RectTransform>();}private void Update(){// Switch inventory bar position depending on player positionSwitchInventoryBarPosition();}private void SwitchInventoryBarPosition(){Vector3 playerViewportPosition = Player.Instance.GetPlayerViewportPosition();if (playerViewportPosition.y > 0.3f && IsInventoryBarPositionBottom == false){rectTransform.pivot = new Vector2(0.5f, 0f);rectTransform.anchorMin = new Vector2(0.5f, 0f);rectTransform.anchorMax = new Vector2(0.5f, 0f);rectTransform.anchoredPosition = new Vector2(0f, 2.5f);IsInventoryBarPositionBottom = true;}else if (playerViewportPosition.y <= 0.3f && IsInventoryBarPositionBottom == true) {rectTransform.pivot = new Vector2(0.5f, 1f);rectTransform.anchorMin = new Vector2(0.5f, 1f);rectTransform.anchorMax = new Vector2(0.5f, 1f);rectTransform.anchoredPosition = new Vector2(0f, -2.5f);IsInventoryBarPositionBottom = false;}}
}

以上参数的值对应Rect Transform的值,比如当位于底部时:

在顶部时对应的值:

将UIInventoryBar脚本添加到UIInventoryBar对象上。

运行程序,效果如下:

http://www.lryc.cn/news/516129.html

相关文章:

  • QT------模型/视图
  • Git - 记录一次由于少输入了一个命令导致的更改丢失
  • nodeJS下npm和yarn的关系和区别详解
  • 党员学习交流平台
  • HTML5 文件上传(File Upload)详解
  • 1.2.1-2部分数据结构的说明02_链表
  • vue elementUI Plus实现拖拽流程图,不引入插件,纯手写实现。
  • linux上使用cmake编译的方法
  • 如何实现el-select多选下拉框中嵌套复选框并加校验不为空功能呢?
  • 源码理解 UE4中的 FCookStatsManager::FAutoRegisterCallback RegisterCookStats
  • Android 根据内存大小显示MTP模式连接PC时的名称
  • 不只是mini-react第一节:实现最简单mini-react
  • 前端路由layout布局处理以及菜单交互(三)
  • 小结:DNS,HTTP,SMTP,IMAP,FTP,Telnet,TCP,ARP,ICMP
  • 【C++】P2550 [AHOI2001] 彩票摇奖
  • 并发服务器框架——zinx
  • Unity 中计算射线和平面相交距离的原理
  • 浅谈棋牌游戏开发流程七:反外挂与安全体系——守护游戏公平与玩家体验
  • 《无力逃脱》V1.0.15.920(59069)官方中文版
  • 六种主流服务器的选择与使用
  • TiDB 升级至高版本提示'mysql.tidb_runaway_watch' doesn't exist 问题处理
  • GRU-PFG:利用图神经网络从股票因子中提取股票间相关性
  • 数字化供应链创新解决方案在零售行业的应用研究——以开源AI智能名片S2B2C商城小程序为例
  • 安卓Activity执行finish后onNewIntent也执行了
  • 数据结构.期末复习.学习笔记(c语言)
  • Kafaka安装与启动教程
  • 根据docker file 编译镜像
  • 联邦学习的 AI 大模型微调中,加性、选择性、重参数化和混合微调
  • android 外挂modem模块实现Telephony相关功能(上网,发短信,打电话)
  • 【计算机视觉技术 - 人脸生成】2.GAN网络的构建和训练