UI Toolkit Runtime Data Binding and Logic

git-amend
18 Feb 202417:10

Summary

TLDR本视频深入探讨了UI工具包的使用,特别是数据绑定技术。通过展示如何将硬币显示与库存系统中的硬币绑定,并实时更新,视频详细介绍了模型、控制器以及可绑定属性的实现。从Unity中静态数据的细节到物品的序列化和反序列化,再到模型的观察数组和控制器的逻辑处理,视频逐步构建了一个完整的库存系统。此外,还介绍了如何使用视图模型和可绑定属性简化UI Toolkit的绑定过程,并通过实际示例演示了绑定的工作原理。

Takeaways

  • 📦 今天我们将深入探讨 UI 工具包,尤其是我们的库存系统和数据绑定。
  • 💰 屏幕上展示了如何将硬币显示绑定到库存中的硬币,并在每一帧添加一个硬币。
  • 📋 我们从上周的模型和控制器开始,并进一步探讨一些可绑定的属性。
  • 🔗 控制器监听视图和模型发布的事件,并决定库存系统的操作。
  • 🔍 项目详情类在 Unity 中用于存储所有类型项目的共有属性。
  • 📜 项目类表示游戏中的单个项目或项目堆栈,包含 ID、详情引用和数量。
  • 🗂 模型包含一个可观察的数组,当数组内容改变时会发布事件。
  • 🛠 控制器需要引用视图和模型,并使用构建器模式来确保依赖项非空。
  • 🔄 控制器订阅视图和模型的事件,并确保视图在开始时是最新的。
  • 🏷 视图模型类用于将数据暴露给视图,同时隐藏模型的细节,通过绑定属性简化数据访问。

Q & A

  • 视频脚本中提到的UI工具箱是什么?

    -UI工具箱指的是Unity中用于构建用户界面的一套组件和功能,它允许开发者创建和管理游戏中的UI元素。

  • 数据绑定在UI工具箱中的作用是什么?

    -数据绑定允许UI元素与数据模型直接连接,使得UI可以自动更新以反映数据模型中的变化,提高了开发效率和用户体验。

  • 脚本中提到的'flyweight pattern'是什么?

    -Flyweight pattern是一种设计模式,用于高效地共享对象,减少内存使用。在脚本中,它被用来让所有相同类型的项目共享相同的Sprite、描述等静态数据。

  • 如何实现Unity中的项目(Item)的序列化和反序列化?

    -项目类需要实现特定的方法来支持序列化和反序列化,以便在游戏保存和加载时能够持久化项目的状态。

  • 脚本中提到的'observable array'是什么?

    -Observable array是一种特殊的数组,当其内容发生变化时,可以发布事件通知其他系统组件,是实现数据绑定的关键部分。

  • 模型(Model)在脚本中扮演什么角色?

    -模型代表游戏中的库存系统,包含所有项目并管理其状态,是控制器(Controller)和视图(View)之间数据交互的核心。

  • 控制器(Controller)在UI工具箱中的功能是什么?

    -控制器负责逻辑处理,根据视图和模型发布的事件做出决策,并管理库存系统的行为,如物品的拖放、堆叠等。

  • 脚本中提到的'view model'是什么?

    -ViewModel是一种设计模式,用于作为视图和模型之间的中介,它将模型的数据以易于视图使用的方式暴露出来,隐藏了模型的复杂性。

  • 如何使用'bindable property'来实现数据绑定?

    -Bindable property是一个可以被视图绑定的属性,它通过getter方法提供数据,并通过特定的属性(如CreatePropertyAttribute)与Unity的UI元素连接。

  • 脚本中提到的Unity的新特性'UI Toolkit'有哪些优势?

    -UI Toolkit提供了更现代和灵活的UI构建方式,支持数据绑定,并且整个Unity编辑器现在都在使用这个新系统,显示了其强大的功能和未来的发展方向。

Outlines

00:00

😀 UI工具箱和数据绑定探索

本段介绍了UI工具箱的深入使用,包括库存系统的内部工作和数据绑定。演示了如何在屏幕上将硬币显示绑定到库存中的硬币,并计划每帧增加一个硬币。内容回顾了上周实现的库存系统UI,该UI在拖拽时会发布事件。介绍了系统架构,包括控制器、视图和模型的交互。详细讨论了静态数据、物品表示、可观察数组以及模型如何代表游戏中的库存。最后,探讨了控制器如何将一切联系起来,并计划在视频最后讨论模型中的绑定属性。

05:00

🛠️ 构建库存系统的控制器

本段聚焦于构建库存系统的控制器,控制器需要知道整个系统的容量,并通过私有构造函数传入。介绍了如何使用构建者模式来确保依赖项不为null,并通过断言来提供调试信息。详细描述了控制器的初始化流程,包括订阅视图和模型的事件,并确保视图与模型保持同步。展示了如何通过构建者模式创建控制器,并连接事件处理程序以处理拖放操作和模型变更。

10:02

🔗 探索Unity中的数据绑定

本段讨论了Unity中的数据绑定,特别是如何将模型中的属性绑定到视图。介绍了创建中间层(ViewModel)来简化数据的暴露和绑定。详细解释了如何创建BindableProperty类来实现单向绑定,并通过Unity属性的CreatePropertyAttribute来连接属性和视图元素。展示了如何在ViewModel中使用BindableProperty,并在模型中添加硬币数量属性。最后,介绍了如何在视图中设置数据源并绑定到ViewModel的属性。

15:06

🎮 测试数据绑定并展望UI Toolkit的未来

本段通过在控制器中添加公共方法来测试数据绑定是否有效,并在Unity中实时增加硬币数量以验证绑定功能。讨论了UI Toolkit的进一步优化,如版本控制和设置事件以通知视图更新。最后,对UI Toolkit的新特性和Unity编辑器的使用进行了展望,并鼓励观众订阅频道以获取更多相关内容。

Mindmap

Keywords

💡UI工具包

UI工具包指的是用于构建用户界面的一套组件和功能库。在视频中,UI工具包被用来进一步探索和实现库存系统的界面和数据绑定功能。例如,视频提到了使用UI工具包来创建和绑定硬币显示到库存中的硬币数量。

💡数据绑定

数据绑定是一种技术,允许UI元素与数据源建立连接,以便在数据源更新时自动反映这些更改。视频中讨论了如何将硬币显示绑定到库存中的硬币数量,以及如何使用数据绑定简化UI与数据模型之间的交互。

💡模型-视图-控制器(MVC)

MVC是一种软件设计模式,用于分离数据模型、用户界面和控制逻辑。视频中提到了控制器如何监听视图和模型发布的事件,并据此做出决策,体现了MVC模式在库存系统中的应用。

💡可观察数组

可观察数组是一种特殊类型的数组,当其内容发生变化时可以通知订阅者。在视频中,模型中的项目存储在一个可观察数组中,当数组内容变化时,会触发事件,控制器会根据这些变化更新库存状态。

💡Flyweight模式

Flyweight模式是一种软件设计模式,用于高效地共享对象。在视频中,所有鱿鱼共享相同的精灵图像和描述,因此可以使用Flyweight模式来节省资源。

💡序列化与反序列化

序列化是将对象状态转换为可以存储或传输的格式的过程,而反序列化是相反的过程。视频中提到了为项目添加序列化和反序列化的方法,以便在游戏的持久性存储中保存和恢复项目状态。

💡Builder模式

Builder模式是一种创建对象的设计模式,允许逐步构建一个复杂对象。在视频中,控制器使用Builder模式来构造,确保所有依赖项都被正确设置,并且提供了一个清晰的方式来创建控制器实例。

💡MonoBehaviour

MonoBehaviour是Unity中的一种组件,可以附加到游戏对象上以实现特定的行为。视频中提到了Inventory类是一个MonoBehaviour,这意味着它可以与Unity编辑器交互,并在游戏运行时执行特定的逻辑。

💡ViewModel

ViewModel是一种设计模式,用于作为视图和模型之间的中间人,提供数据和命令以供绑定。在视频中,ViewModel用于封装库存数据,并提供可绑定的属性,如硬币数量,以简化视图与数据的交互。

💡Unity属性

Unity属性是Unity中的一种特性,允许将公共属性暴露给Unity的Inspector窗口。视频中提到使用Unity属性来创建可绑定的属性,这样可以通过Unity编辑器直接绑定到UI元素。

Highlights

介绍了UI工具包在库存系统中的深入应用,包括数据绑定。

展示了如何将硬币显示绑定到库存中的硬币,并每秒增加一个硬币。

回顾了上周实现的UI库存系统,该系统在拖拽时发布事件。

详细解释了控制器如何监听视图和模型发布的事件,并做出决策。

深入探讨了模型的内部工作,包括静态数据和可观察数组的使用。

讨论了如何使用享元模式来优化游戏中所有物品的共享属性。

展示了如何在Unity中创建具有引用静态细节的实例化项目。

解释了模型如何使用可观察数组来管理游戏中的库存,并发布变更事件。

介绍了控制器的逻辑,包括如何处理拖放事件和库存操作。

讨论了如何通过构建器模式创建库存控制器,并保持构造函数的私有性。

展示了如何订阅视图和模型的事件,以及如何刷新UI以保持与模型同步。

介绍了如何处理复杂的拖放场景,例如将物品移动到非空槽中。

解释了如何在Unity中使用Inventory类作为MonoBehaviour来设置库存系统。

讨论了数据绑定的概念,以及如何在UI中显示模型中的简单值。

介绍了创建可绑定属性的方法,以及如何在视图模型中使用它们。

展示了如何在Unity中将视图模型与UI元素绑定,以实现数据的动态更新。

讨论了Unity UI Toolkit的新特性和优化,以及它们在编辑器中的应用。

Transcripts

play00:00

today I want to go a little further with

play00:02

UI toolkit and explore not just the

play00:04

inner workings of our inventory system

play00:06

but data binding as well you can see on

play00:08

the screen I've bound the coin display

play00:10

to the coins that are kept in my

play00:11

inventory and I'm giving myself another

play00:13

coin every frame we'll start where we

play00:16

left off last week by covering the model

play00:18

in the controller and then we'll take it

play00:19

another step further with some bindable

play00:21

properties it might be useful to watch

play00:24

last week's video before watching this

play00:25

one so I'll put a link for it but it's

play00:27

not strictly necessary let's get right

play00:29

into it

play00:34

last week we implemented a UI for our

play00:36

inventory system that publishes an event

play00:38

when one slot is dragged onto another

play00:41

let's have a look at these other seams

play00:42

in our diagram in our system the

play00:44

controller listens to events published

play00:46

from The View and from the model and

play00:48

then makes decisions about the inventory

play00:50

system let's dive into the part that the

play00:52

player doesn't see we'll start with the

play00:55

details which is static data that all

play00:57

items of a particular type share next an

play01:00

item will be the representation of an

play01:02

item or stack of items in the game the

play01:05

items will live in an observable array

play01:07

that will publish an event when the

play01:09

contents of the array change the model

play01:11

represents our inventory in the game and

play01:13

all of its properties finally we'll look

play01:15

at the controller and how everything is

play01:17

wired up together when we're done all

play01:19

that we'll have a look at binding

play01:20

properties in the model to the view

play01:23

let's take a look at one of these item

play01:24

details in unity these are common

play01:27

properties to all items of a particular

play01:29

type type any item that we instance in

play01:31

the game will have a reference to these

play01:33

static details this is going to let us

play01:36

use the flyweight pattern for all of the

play01:37

items since all squids share the same

play01:40

Sprite and they can only stack to one

play01:43

have the same description Etc let's have

play01:45

a look at this in

play01:47

code if I take away all my Odin tags

play01:50

you'll see there's not too much to this

play01:51

really it's exposing a few properties

play01:53

there that we can manipulate in the

play01:54

editor but the most important thing here

play01:57

is that it has its own create method

play01:59

this gives us a a little Factory method

play02:00

to be able to create an instance of an

play02:02

item that has a reference to these

play02:04

details at runtime I'm just going to

play02:06

restore my Odin tags for the rest of the

play02:08

demo but let's go and have a look at the

play02:10

item class next so an actual item is

play02:14

going to have its own ID to represent

play02:16

itself in our world in our game a

play02:18

reference to the details and it's going

play02:20

to have a quantity so in case we need to

play02:22

stack it in the future we'll add some

play02:24

methods so that an item knows how to

play02:26

serialize and deserialize itself for

play02:28

persistence

play02:30

now that we're familiar with those

play02:31

things we can start having a look at the

play02:33

model now the model is going to house

play02:35

all of the items inside of an observable

play02:38

array and if you've been watching this

play02:39

channel for a while you know about an

play02:41

observable list already this is very

play02:43

similar so we're not going to create it

play02:44

from scratch we'll just walk through it

play02:46

let's have a look at the interface first

play02:49

you can see that it's going to publish

play02:50

an event called any value changed

play02:53

will'll invoke this event anytime one of

play02:55

our public methods is called it also

play02:57

exposes a few properties like count and

play02:59

the ability just to get whatever's

play03:01

inside any particular index let's close

play03:04

that up and we can have a look at the

play03:06

actual implementation so there's an

play03:08

array of type T we assign an empty

play03:10

delegate to the action so that we never

play03:12

have to check it for null its

play03:14

Constructor accepts a size as well as an

play03:17

ey list which could be potential items

play03:19

to start the inventory with the private

play03:21

method invoke will invoke the event with

play03:23

a reference to the items we come down a

play03:26

little bit further we can see the swap

play03:27

method uses tupple deconstruction to

play03:30

just swap one item with another in the

play03:32

array next we have a clear method that

play03:34

will empty out our array try add will'll

play03:37

try to add an item to the inventory in

play03:39

the first available slot if there is one

play03:42

try remove we'll look for a specific

play03:43

item in the array and try to remove it

play03:47

next we're going to encapsulate those

play03:48

events that are published by the

play03:50

observable array with our own event

play03:52

we'll call that on model changed is just

play03:55

a wrapper for the event that's one level

play03:57

deeper down so when someone subscribed

play03:59

to on model changed they're really

play04:01

subscribing to the event published by

play04:03

the array and likewise when they

play04:05

unsubscribe in the models Constructor we

play04:07

can pass in some starting item details

play04:09

as well as the capacity and it'll use

play04:11

that information to create the new array

play04:14

iterate over all of the item details

play04:16

that we've passed in and try to create

play04:18

and add one new item into our array now

play04:21

we'll add a few public methods here that

play04:23

will be operations that we can use to

play04:25

manipulate our inventory array now these

play04:28

first few method me don't really have

play04:30

too much logic they're just passrs

play04:32

really even the swap method is

play04:34

essentially a pass through the combined

play04:36

method will have a little bit more logic

play04:38

basically it's going to Total the items

play04:40

in both slots put the total into the

play04:42

destination slot and clear out the

play04:44

source slot and that's it for the model

play04:47

we're going to come back to visit this

play04:48

again when we talk about binding at the

play04:50

end of the video now let's have a look

play04:52

at our controller that's going to do all

play04:54

the thinking and logic having to do with

play04:56

our inventory system first of all this

play04:58

is going to need a reference to both the

play05:00

view and the model and it's going to

play05:02

know the capacity of the entire system

play05:04

these values are going to get passed in

play05:06

through a private Constructor we're

play05:08

going to create a builder for this so

play05:09

we'll keep the Constructor private

play05:11

normally when assembling a service like

play05:13

this you want to make sure that none of

play05:15

the dependencies are actually null

play05:17

previously we've used techniques like a

play05:19

preconditions class that would actually

play05:21

throw exceptions debug. assert will do

play05:24

something similar except it's not going

play05:25

to Halt the operation of your program

play05:27

but it will give you a nice Orange

play05:29

message in your console log once we're

play05:31

pass that we can assign the references

play05:33

to their fields next I want to start a

play05:35

co- routine that's going to do all my

play05:37

initialization but this is not a mono

play05:39

Behavior The View on the other hand is a

play05:42

mono Behavior so I can run a co- routine

play05:44

based on that mono Behavior even though

play05:46

the initialized method is actually part

play05:49

of a pure C Clause so let's define that

play05:52

as I numerator initialize the view

play05:55

already has a method defined to

play05:56

initialize its own uxl document we just

play05:59

need to pass it in the capacity so we'll

play06:01

wait for that to finish and then

play06:02

continue on by subscribing to events

play06:04

we're going to fill this part in in a

play06:06

little bit we'll have to subscribe to

play06:08

events in the view the model and then we

play06:10

can just run a refresh to make sure that

play06:12

the view is up to date when we start

play06:14

let's quickly put together a builder for

play06:16

this we're going to pass in a reference

play06:18

to our view but the model is something

play06:21

that we'll create within the Builder we

play06:23

can pass in our starting items here

play06:25

we'll Define an initial capacity of 20

play06:27

and then to enforce that we are all

play06:29

always passing in the view will make it

play06:30

a parameter of the Constructor we'll

play06:33

have some additional methods here so

play06:34

that we can pass in optional item

play06:36

details if we want starting items we

play06:38

could also Define a different capacity

play06:40

than the default if we wanted to finally

play06:42

in the build method we're going to

play06:44

create a new model we can start that off

play06:46

with either the optional starting items

play06:48

or just an empty array then we just run

play06:51

the private Constructor and return our

play06:52

new inventory controller so now we can

play06:55

build a controller let's connect up

play06:57

those events I'll just collapse the

play06:59

Builder section so it's out of the way

play07:02

so the view has an event called on drop

play07:04

that we want to subscribe to and handle

play07:06

the model has its own event on model

play07:09

changed we also want to be able to

play07:11

handle that and we'll need one

play07:13

additional method that just makes sure

play07:15

that the view is up to date with the

play07:17

model to refresh our slots what we need

play07:19

to do is just iterate over our capacity

play07:23

getting each item from the model if it's

play07:26

null we want to set that particular slot

play07:28

in our UI to empty slot otherwise we'll

play07:31

pass in the details the slot needs to

play07:32

know about itself which item it's

play07:35

representing its icon and quantity now

play07:38

just above that we'll have the handle

play07:39

model change now when that event fires

play07:42

it actually sends us a list of all the

play07:43

items right now I'm just going to do a

play07:45

blanket refresh view but you could

play07:47

optimize this a little bit and maybe

play07:49

just refresh the item slots that

play07:51

actually were changed our handle drop

play07:54

method I'll place right above that now

play07:56

handle drop has to handle various

play07:58

scenarios when one slot gets dropped

play08:00

onto another so we'll start with the

play08:02

simplest ones first and that would be

play08:04

what happens if you drop a slot onto an

play08:07

empty slot or you drop it onto the slot

play08:10

that you actually dragged from in both

play08:12

cases we can just do a swap you might be

play08:15

tempted to think let's just bail out of

play08:17

here if we're dropping a slot onto

play08:18

itself but actually I do want all the

play08:20

events to fire right now that's going to

play08:23

make sure that the view is refreshed but

play08:24

in the future we might have sound

play08:26

effects and so on now for more complex

play08:28

scen scarios where we're moving to a

play08:30

non-empty slot I first want to know what

play08:33

type of item this is and that is the ID

play08:35

that's stored in the item details so

play08:38

let's grab those IDs out of the details

play08:41

and we'll just store them locally here

play08:42

for comparison there's really two

play08:44

scenarios here one is that in the first

play08:47

case the IDS match and the item is

play08:50

allowed to be stacked if it's a

play08:52

stackable item we're going to use the

play08:53

models combined method and just pass

play08:55

those in otherwise we're just swapping

play08:57

positions we'll use the swap method

play08:59

we're pretty much done with the

play09:00

controller logic now if you had been

play09:03

looking in the repository before I

play09:05

released this video you probably up to

play09:07

speed on everything that we've covered

play09:08

so far really we just need to come over

play09:10

to the inventory class which is a monob

play09:12

behavior we're going to expose to Unity

play09:14

this will allow us to set up everything

play09:16

we want to construct and have a

play09:17

reference to the view and then inside of

play09:20

unity we can link these things up and

play09:22

use them to create our controller so in

play09:25

our awake method here we can just use

play09:27

our Builder to pass in those parameters

play09:30

run the build method and we're done the

play09:32

inventory should be running for

play09:35

us so why don't we jump back into Unity

play09:38

I'm going to hit controlr refresh my

play09:41

assets and hit

play09:42

play there we go we got our inventory on

play09:45

the screen let's just make sure that

play09:46

everything is working the way we think

play09:48

it should stacking is working

play09:50

great we can swap items around drag into

play09:53

empty slots yeah drag into itself

play09:57

perfect okay that's all the functional

play09:59

we've built so far looking

play10:01

good so with our inventory looking

play10:04

pretty good let's start talking about

play10:05

binding if I want to show a simple value

play10:08

in my UI that doesn't really have a lot

play10:10

of logic and just really needs to

play10:12

display the value of a property that we

play10:14

have inside the model one thing we can

play10:16

do is binding I'm going to use coins for

play10:19

this example so I'm going to add a few

play10:20

styles to my USS file here so we've got

play10:24

a parent container called coins it's

play10:26

very simple just going to display things

play10:28

in a row it has a child that's going to

play10:30

be a 40x40 container with a background

play10:33

image that has my little coin icon and

play10:35

beside that I'm going to place a

play10:37

label in our inventory view we're

play10:40

procedurally creating our UI so right

play10:43

above where we defined the ghost icon

play10:45

let's define a coins visual element

play10:47

that's going to be a child of the

play10:49

inventory that coins element is going to

play10:51

need two children as I just mentioned

play10:54

one is going to be for the label the

play10:56

label will show how many coins we

play10:58

actually have so I'll just create a new

play10:59

label here and I'll add it to the coins

play11:02

now we don't have any property to

play11:04

actually bind to this label yet so I'm

play11:06

just going to put a note in here and

play11:07

we'll come back to this after we've

play11:09

actually created something to bind to it

play11:12

is possible to pass a reference to the

play11:13

model directly into the view and then

play11:15

bind to a property on the model directly

play11:18

but I'm going to create a bit of a

play11:20

middle man here now often you'll hear

play11:23

people refer to this as a view model you

play11:26

see this most often in mvvm archit

play11:29

textures where a view model exposes data

play11:31

from the model in such a way that it's

play11:34

easy to consume by the view it hides all

play11:36

the details generally you use it to

play11:39

expose public properties and commands

play11:41

for binding to support this I'm going to

play11:43

create a new class bindable property

play11:45

which will be of any type t a bindable

play11:48

property will allow us to bind to

play11:49

Something in the model without actually

play11:51

exposing the model our view model class

play11:54

can contain a combination of bindable

play11:56

properties and just regular properties

play11:58

too let's start with the bindable

play12:00

property now I'm going to make this

play12:02

bindable property a one-way binding that

play12:04

means I only really need to have a

play12:06

getter now getter is just a function

play12:08

that's going to get whatever data it is

play12:11

that I want to supply now if you wanted

play12:13

to have a Setter it would kind of go the

play12:14

reverse so I'll just make a note here

play12:16

you could add an action of a type T that

play12:19

would act as a Setter it would just be

play12:20

the reverse of what we're about to do

play12:22

here I'm going to give this a private

play12:24

Constructor that accepts the getter now

play12:26

let's have a public property here that

play12:28

will allow us to execute the getter

play12:30

whenever we want something we're going

play12:33

to add the create property attribute now

play12:35

this comes from you can see up top there

play12:38

using unity. properties this attribute

play12:40

is going to allow us to connect a

play12:42

property to a visual element finally

play12:45

let's have a little static creation

play12:47

method this will give us a little

play12:49

shorthand for creating bindable

play12:50

properties so let's have a look at how

play12:53

we're going to use this in a view model

play12:55

type of scenario now the view model I

play12:56

want to have more information than just

play12:58

the coins we're already passing the

play13:00

capacity into the view we might as well

play13:02

add that to our view model as well then

play13:04

way we can just pass the model and we

play13:07

don't have to pass any extra parameters

play13:08

The View model can really encapsulate

play13:10

all that data now the coins can be a

play13:12

bindable property of type string because

play13:15

I want to be updating the label text to

play13:17

construct The View model we'll actually

play13:19

pass in a reference to the model so we

play13:21

can bind to it and we'll set the

play13:23

capacity and then create a new bindable

play13:25

property of type string and that'll be a

play13:28

bind to the model coins property then as

play13:31

part of the getter we'll call two string

play13:34

so that means our model needs to keep

play13:35

track of our coins now let's jump over

play13:37

to the model and add one more property

play13:39

here it can just be an integer for coins

play13:41

we're close to set up now but when we're

play13:44

creating our view previously we were

play13:46

just passing in the capacity let's

play13:48

change this so that we're actually

play13:49

passing in a new view model we can just

play13:52

construct it right here when we call our

play13:55

initialized view method instead of the

play13:57

capacity we'll say new view model and

play14:00

we'll pass in the modeling capacity here

play14:02

that'll create our new view model The

play14:04

initialized View signature is expecting

play14:06

an integer so we're going to have to

play14:07

make just a couple more adjustments for

play14:09

that if we jump over to the inventory

play14:12

view we can replace that with a view

play14:14

model now that we've changed that we

play14:16

need to change the reference to size

play14:19

everywhere that's going to be view

play14:20

model. capacity and one more spot down

play14:24

here then over in our storage view

play14:27

abstract class we also need to change

play14:29

the method signature down here I'll just

play14:32

scroll down and change it okay with

play14:34

those references all fixed up we can now

play14:36

come back over to the view and actually

play14:38

bind a property to a visual element to

play14:42

do that we can set the coins to have a

play14:45

data source of the view model. coins

play14:48

this means now that coins and any of its

play14:51

children have access to that property on

play14:53

The View model and so we can use the set

play14:56

binding method on the coins label like

play14:58

so what we're doing here is binding the

play15:01

label. text field to the actual bindable

play15:05

property string. value that property

play15:08

path is also a class of the unity.

play15:12

properties namespace now notice at the

play15:15

bottom here there's different binding

play15:16

modes we're using two target which means

play15:18

this is a getter but two Source would be

play15:21

a Setter you can have two-way and

play15:23

there's a couple other ones that two

play15:24

target once will only set it one time

play15:26

just about code complete but I forgot to

play15:28

put my icon in here so let's make that a

play15:31

child of the coins object as well I've

play15:33

already written all the styling for that

play15:34

so it should pop my icon into place how

play15:37

are we going to test this thing what if

play15:39

we come back over to the controller and

play15:41

we make a public method to add coins so

play15:44

we can just taking an amount and then

play15:45

we'll update our model with that many

play15:48

coins now that should be fine and out in

play15:51

the actual inventory class which is a

play15:52

mono Behavior what if we just add one

play15:55

more coin to our inventory every frame

play15:58

that way we'll know for sure if the

play15:59

binding is

play16:01

working let's jump back into Unity

play16:04

refresh and hit play there we go coins

play16:07

is just going up like crazy perfect

play16:11

that's exactly what we expect now you

play16:13

can use the same kind of technique for

play16:15

health or for anything else the bindings

play16:18

can be a little bit simpler if you want

play16:19

to go directly to the model or some

play16:22

other data structure but if you kind of

play16:24

want to have a middleman abstraction

play16:25

like this view model then the binding

play16:28

property can be very useful for you

play16:30

there's a few optimizations you can make

play16:32

to bindings for UI toolkit like

play16:34

versioning or you can also uh set events

play16:38

to fire that lets the view know that

play16:40

it's time to update whatever is

play16:41

referenced in The Binding so far we've

play16:44

really just scratched the surface of

play16:45

what's possible with bindings and some

play16:47

other new features of UI toolkit and

play16:49

they seem to be working on it a lot it's

play16:51

definitely the entire editor is now

play16:53

using UI toolkit I'm sure we'll be

play16:55

talking about this more in future videos

play16:57

as we keep working on various projects

play17:00

and things so uh hit the like button

play17:02

subscribe and hit the Bell if you don't

play17:04

want to miss any of those otherwise

play17:06

maybe click on one of these boxes on

play17:07

your screen and I'll see you there

Rate This

5.0 / 5 (0 votes)

Related Tags
Unity开发UI工具包数据绑定游戏设计库存系统模型视图控制器逻辑可观察数组事件处理视图模型交互式UI
Do you need a summary in English?