找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 29|回复: 1

[经验] 动态修改Live2D组件动作

[复制链接]
发表于 昨天 12:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×

文章也同步到了仓库里, 喜欢的话给我的仓库点个 Star 吧: https://github.com/Koji-Huang/KojiRenpyBox

`Renpy` 官方的 `Live2D` 组件提供了 `blend_parameter` 来混合单个动作却没有提供一个自定义混合动作的接口, 很巧的是我要用到了, 在吃了几个晚上源码的史后(以前受人委托研究过这个模块, 但当时并没有成功), 就有了这篇文章

首先, 先解释一下 `Renpy Live2D` 源码内的重要模块
[RenPy] 纯文本查看 复制代码
class Live2DExpression(object)  # 用于合成参数的类

class Live2DCommon(object):  
    """
    让同一个 Live2D 文件使用共同参数的类,
    也就是说, Live2D 文件的信息是保存在这个类里而不是某个全局变量里的
    """
    
    
    # attributes 参数储存了已知的动作参数, 我们需要查询某个动作是否存在是可以来这里查询
    attributes: set[str, ..., ...]
    
    
    """
    motions 参数储存了该 Live2D 文件的动作
    Motion 对象有一个 get 方法, 该方法接收 (st, fade_st, do_fade_in, do_fade_out) 这些参数
    并返回该动作在这些时间下对应的 Paramter 参数
    """
    motions: dict[str: Motion, ...]


class Live2D(renpy.display.displayable.Displayable):
    """
    我愿称之为调用 Live2DCommon 的组件, 同时也是提供接口的组件
    """
    
    # 此 Live2D 的 Common
    common: Live2DCommon
    
    # 更新 common 状态来达到更新组件状态的函数
    def update(self, common, st, st_fade)
    
    # 直接更新组件参数的函数 [url=https://doc.renpy.cn/zh-CN/live2d.html#blend_parameter]https://doc.renpy.cn/zh-CN/live2d.html#blend_parameter[/url]
    def blend_parameter(self, name, blend, value, weight=1.0):


我们先看看 `Renpy` 源码是怎么将动作应用到组件上的吧, 这部分代码在 `class Live2D - update` 函数里
[RenPy] 纯文本查看 复制代码
# Apply the motion.

# 获取各个 motion 的 Paramter
motion_data = motion.get(st, st_fade, do_fade_in, do_fade_out)

# 遍历各个参数
for k, v in motion_data.items():

    kind, key = k
    factor, value = v

    if kind == "PartOpacity":
        common.model.set_part_opacity(key, value)
    elif kind == "Parameter":
        # 应用参数到 common 上
        common.model.set_parameter(key, value, factor)
    elif kind == "Model":
        # 应用参数到 common 上
        common.model.set_parameter(key, value, factor)



`motion` 参数为一个 `Motion` 对象, `common` 就是该组件自己的 `common`, `common` 对象的 `model` 参数就是 `Live2D` 模型的渲染模型, 这里是把参数逐个应用到该模型上

看懂了上面的内容, 我们就可以自己实现一个改变动作的效果了, 我们可以通过传入 `update_function`(https://doc.renpy.cn/zh-CN/live2d.html#Live2D 下的 `update_function` ) 来修改动作的效果, 这个函数的结算发生在上面的代码之后, 例如:

[RenPy] 纯文本查看 复制代码
def update_function(obj, st):
    common = obj.common
    motion = common.motions

    # 获取组件的动作参数
    attributes = obj.common.attributes
    
    # 随机一个表情
    target = attributes[randint(len(attributes))]
    if target == 'null': target = 'still'
    
    # 获取这个表情进行了 3 秒钟的参数
    motion_data = motion[target].get(3.0, 0, 0, 0)

    # 将参数应用到模型上
    for k, v in motion_data.items():

        kind, key = k
        factor, value = v

        if kind == "PartOpacity":
            common.model.set_part_opacity(key, value)
        elif kind == "Parameter":
            # 最好使用 Live2D 对象的 blend_parameter 来应用参数
            # 而不是 update 函数里的 common.model.set_parameter
            obj.blend_parameter(name=key, value=value, weight=0.5, blend="Add")
        elif kind == "Model":
            obj.blend_parameter(name=key, value=value, weight=0.5, blend="Add")

    # 立即更新
    return 0.0

将此函数传入组件内, 此时应该看到一个不停切换动作的 `Live2D` 组件. 此外需要注意的是, 每次 `interaction` 后 `st` 轴都会重置, 所以如果考虑一些高级效果的话, 我建议建类或者去研究一下 `Live2DState` 对象, 该对象会保留 `old`, `new` 的 `Live2D` 对象来保证动作连贯

评分

参与人数 1干货 +3 收起 理由
ZYKsslm + 3 精品文章!

查看全部评分

发表于 昨天 14:32 | 显示全部楼层
那很强了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|RenPy中文空间 ( 苏ICP备17067825号|苏公网安备 32092302000068号 )

GMT+8, 2025-6-16 06:44 , Processed in 0.048609 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表