Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[UE] Bug: 编辑器器下正常,打包后静态函数调用报函数为空 #1882

Open
3 tasks done
luzhaosama opened this issue Oct 28, 2024 · 8 comments
Open
3 tasks done
Assignees
Labels
bug Something isn't working Unreal

Comments

@luzhaosama
Copy link

luzhaosama commented Oct 28, 2024

前置阅读 | Pre-reading

Puer的版本 | Puer Version

1.0.5

UE的版本 | UE Version

5.4.4

发生在哪个平台 | Platform

win

错误信息 | Error Message

V8里,部分静态方法名称大小写改变,例如UKismetMathLibrary::Atan,在遍历输出库里所有的方法以后,变成了atan。
image

问题重现 | Bug reproduce

编写如下方法,然后打PC包
image
会看到这些log
image
image
红色部分是大小写发生改变的地方

Tasks

No tasks being tracked yet.
@luzhaosama luzhaosama added bug Something isn't working Unreal labels Oct 28, 2024
@chexiongsheng
Copy link
Collaborator

遍历为小写不代表有问题。
修正机制不是让这个类变正确,而是发生找不到属性时(比如请求Atan),先转换成FName,然后转换回字符串,所以知道由于FName忽略大小写导致变成atan了,然后返回atan属性。

你通过KismetMathLibrary::Atan访问报错了才代表有问题。

@luzhaosama
Copy link
Author

提交一个运行时的报错
image

@chexiongsheng chexiongsheng changed the title [UE] Bug: [UE] Bug: 编辑器器下正常,打包后静态函数调用报函数为空 Oct 28, 2024
@chexiongsheng
Copy link
Collaborator

打包后ue的FName默认不区分大小写,这个FName 转字符串是什么样取决于它第一次构造时用的是哪个字符串。

v8的成员函数和属性支持自动规避如上特性,但静态函数和变量尚未支持。

可以用proxy来规避这问题,在这里略微修改下:
https://github.com/Tencent/puerts/blob/master/unreal/Puerts/Content/JavaScript/puerts/uelazyload.js#L18

改为

    function getFName(str) {
        // !!我这里写死了只是简单的测试下效果,实际上得到UE那先转FName,然后ToString回传
        return 'clamp';
    }
    
    function FNameCaseFix(cls) {
        let proxy = new Proxy(cls, {
            get: function(cls, name) {
                let m = cls[getFName(name)]; 
                Object.defineProperty(cls, name, {
                    value: m,
                    writable: false,
                    configurable: true,
                    enumerable: false,
                });
                return m;
            }
        });
        Object.setPrototypeOf(cls, proxy);
        return cls;
    }

    let UE = new Proxy(cache, {
        get : function(classWrapers, name)
        {
            let value = classWrapers[name];
            if (value === undefined)
            {
                value = loadUEType(name);
                classWrapers[name] = FNameCaseFix(value);
            }
            return value;
        }
    });

@chexiongsheng
Copy link
Collaborator

上面的修正代码改为Object.getOwnPropertyDescriptor后,然后Object.defineProperty会比较好些

@rhm0325
Copy link
Contributor

rhm0325 commented Oct 30, 2024

QuickJs 里的成员变量和成员函数 都可以用类似上面的思路来修改吗

@chexiongsheng
Copy link
Collaborator

QuickJs 里的成员变量和成员函数 都可以用类似上面的思路来修改吗

可以的。

@luzhaosama
Copy link
Author

上面的修正代码改为Object.getOwnPropertyDescriptor后,然后Object.defineProperty会比较好些

如果一个类里有两个同名但是大小写不一致的成员,可能也会出现获取错误的问题。但是目前的方案已经能保底了,可以使用,期待有一个更稳妥的方案。

@chexiongsheng
Copy link
Collaborator

上面的修正代码改为Object.getOwnPropertyDescriptor后,然后Object.defineProperty会比较好些

如果一个类里有两个同名但是大小写不一致的成员,可能也会出现获取错误的问题。但是目前的方案已经能保底了,可以使用,期待有一个更稳妥的方案。

这种自己加个静态绑定声明可以解决。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Unreal
Projects
None yet
Development

No branches or pull requests

3 participants