我怎样才能获得"免费"在iOS上的Unity3d中的内存?

时间:2013-09-24 07:45:53

标签: c# ios objective-c unity3d

我遇到了一个问题:如果我尝试使用Texture2D.ReadPixels创建屏幕截图,游戏会在某些设备上崩溃(最值得注意的是iPod 4G)。据说,它是因为内存不足而发生的。在创建屏幕截图之前,我想检测一下,如果我可以安全地分配所需的内存量,并且如果我认为我会崩溃,则向玩家显示警告。

但是,似乎像Mono VM一样管理像纹理这样的资源。当我有大约16mb的地图集时,System.GC.GetTotalMemory返回9mb。所以,似乎我必须为此编写一个插件。

(有一节描述我没有收到低内存警告,但似乎我误解了它,并且在Objective-C级别上,警告成功提出)。

如何在不崩溃的情况下获得可以分配的“免费”内存量?可能还有其他方法可以实现我想要的功能吗?

3 个答案:

答案 0 :(得分:6)

解释你自己的答案:这不是客观的C代码,而是普通的旧C,使用Mach API来从内核获取统计信息。 Mach API是由XNU导出的低级API,它是由顶层(导出BSD API,如我们知道并喜欢UN * X的常用系统调用)和底层(即Mach)组成的混合内核。 该代码使用Mach“host”抽象,其中(除其他外)提供有关资源的OS级别利用率的统计信息。

具体来说,这是一个完整的注释:

#import <mach/mach.h>       // Required for generic Mach typedefs, like the mach_port_t
#import <mach/mach_host.h>  // Required for the host abstraction APIs.

extern "C" // C, rather than objective-c
{

    const int HWUtils_getFreeMemory()
    {
        mach_port_t host_port;             
        mach_msg_type_number_t host_size;
        vm_size_t pagesize;

        // First, get a reference to the host port. Any task can do that, and this
        // requires no privileges
        host_port = mach_host_self();
        host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);

        // Get host page size - usually 4K
        host_page_size(host_port, &pagesize);

        vm_statistics_data_t vm_stat;

        // Call host_statistics, requesting VM information. 

        if (host_statistics(host_port,  // As obtained from mach_host_self()
             HOST_VM_INFO,              // Flavor - many more in <mach/host_info.h>(host_info_t)&vm_stat,                  // OUT - this will be populated
             &host_size)                // in/out - sizeof(vm_stat). 
              != KERN_SUCCESS)         
            NSLog(@"Failed to fetch vm statistics"); // log error

        /* Stats in bytes */
        // Calculating total and used just to show all available functionality

        // This part is basic math. Counts are all in pages, so multiply by pagesize
        // Memory used is sum of active pages, (resident, used)
        //                       inactive,      (resident, but not recently used)
        //                   and wired (locked in memory, e.g. kernel)

        natural_t mem_used = (vm_stat.active_count +
                              vm_stat.inactive_count +
                              vm_stat.wire_count) * pagesize;
        natural_t mem_free = vm_stat.free_count * pagesize;
        natural_t mem_total = mem_used + mem_free;
        NSLog(@"used: %u free: %u total: %u", mem_used, mem_free, mem_total);


        return (int) mem_free;
    }

答案 1 :(得分:4)

所以,在一些客观的大师的帮助下,我已经能够找到正在做我想要的代码片段。我必须警告你,我不明白这个Obj-C代码到底做了什么,并且它被认为是“黑客”;然而,事实证明这是解决我问题的最佳方法。

在插件.mm文件中:

#import <mach/mach.h>
#import <mach/mach_host.h>

extern "C"
{

    const int HWUtils_getFreeMemory()
    {
        mach_port_t host_port;
        mach_msg_type_number_t host_size;
        vm_size_t pagesize;

        host_port = mach_host_self();
        host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
        host_page_size(host_port, &pagesize);

        vm_statistics_data_t vm_stat;

        if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS)
            NSLog(@"Failed to fetch vm statistics");

        /* Stats in bytes */
        // Calculating total and used just to show all available functionality
        natural_t mem_used = (vm_stat.active_count +
                              vm_stat.inactive_count +
                              vm_stat.wire_count) * pagesize;
        natural_t mem_free = vm_stat.free_count * pagesize;
        natural_t mem_total = mem_used + mem_free;
        NSLog(@"used: %u free: %u total: %u", mem_used, mem_free, mem_total);

        return (int) mem_free;
    }

}

在我的硬件实用程序文件中:

    [DllImport("__Internal")]
    static extern int HWUtils_getFreeMemory();

#if UNITY_IPHONE && !UNITY_EDITOR
    public static int GetFreeMemory()
    {
        return HWUtils_getFreeMemory();
    }
#endif

答案 2 :(得分:1)

读取Unity3D(iOS和Android)上的像素时,我也遇到了一些GL_OUT_OF_MEMORY错误。在我做了很多测试之后,主要问题是当我使用ReadPixels方法(大约> 40个绘制调用)拍摄屏幕截图时,我的游戏绘制调用太高了。也许你应该调查这个因素。