在web前端领域,在UI制作方面有着悠久的历史,且一直都基于html+js+css技术,更利于技术的沉淀,是否能把web领域的优秀实践借鉴到游戏中呢?
上古时期流行的是dreamwaver的可视化编辑方式;而开源兴起后,作为最活跃的开源社区,相关技术百花齐放。react,angular,vue就是这些方案中的佼佼者。
其中react应该是最早探索非web领域使用的方案,比如react native正是这方面的探索,也验证了这种模式也适用于原生UI的制作。到了 React 16.2.0之后,更进一步的支持开发者定制自己的Host渲染器:于是有人将react适配到微信小程序,适配到three.js来做3D游戏,嵌入式系统等等,正所谓“Learn once, Write anywhere”。而本文正是利用该能力实现react在UE4上的移植。
首先,UE4下使用react你必须得有个js环境。试试这个:puerts。
其次,你得实现react的一些钩子。说白了也不高深,就是一些回调,react在UI控件的创建,更新,删除时会调用这些回调:
创建控件调用createInstance回调,告诉你要创建的是啥UI控件(Button,Text。。),属性(宽,高,颜色。。)是什么。
控件添加到UI树上调用appendChild回调,告诉你某UI控件,其父节点是什么。
控件属性的更新调用prepareUpdate\commitUpdate,告诉你原属性是啥,新属性是啥。
控件的删除调用removeChild回调。
。。。
细节可以参见源码。仅200多行代码,即完成了react和umg的对接。
看个UI组件的实例:
class StatusBar extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
if ((props.initialPercent || 0) < 0) {
throw new Error('initialPercent < 0');
}
this.state = {
percent: props.initialPercent || 0.5
};
}
get color(): LinearColor {
return {R: 1 - this.state.percent , G: 0, B: this.state.percent};
}
onIncrement = () => this.setState({percent: this.state.percent + 0.01});
onDecrement = () => this.setState({percent: this.state.percent - 0.01});
render() {
return (
<HorizontalBox>
{this.props.name}({this.state.percent.toFixed(2)})
<ProgressBar Percent={this.state.percent} Slot={SlotOfProgressBar} FillColorAndOpacity={this.color}/>
<Button OnClicked={this.onIncrement} >+</Button>
<Button OnClicked={this.onDecrement} >-</Button>
</HorizontalBox>
);
}
}
用过react的人会很熟悉,但不一定每个人都用过,说明下:
该组件的使用接着看代码:
class Hello extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
}
render() {
return (
<CanvasPanel>
<VerticalBox Slot={SlotOfVerticalBox}>
{this.props.names.map((name, idx) => <StatusBar name={name} key={idx}/>)}
</VerticalBox>
</CanvasPanel>
);
}
}
//渲染到屏幕
ReactUMG.render(<Hello names={["Health:", "Energy:"]}/>);
代码说明:
最终效果
这个尝试只是一个抛砖引玉,有兴趣的可以试试并一起完善。目前也只提供了UE4版本,如果在Unity也想使用,可以按照UE4的思路整一发,毕竟也没几行代码。