国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Unity與iOS交互(2)——接入SDK

這篇具有很好參考價(jià)值的文章主要介紹了Unity與iOS交互(2)——接入SDK。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

【前言】

接入Android和iOS SDK有很多相同的地方,建議先看下Android SDK如何接入。

?【UnityAppController詳解】

?整個(gè)程序的入口在MainApp文件下的main.mm文件中,先加載了unityframework,然后調(diào)用runUIApplicationMain。源碼如下:(這些源碼在Xcode工程里都有)

#include <UnityFramework/UnityFramework.h>

UnityFramework* UnityFrameworkLoad()
{
    NSString* bundlePath = nil;
    bundlePath = [[NSBundle mainBundle] bundlePath];
    bundlePath = [bundlePath stringByAppendingString: @"/Frameworks/UnityFramework.framework"];//獲取完整的UnityFramework的路徑

    NSBundle* bundle = [NSBundle bundleWithPath: bundlePath];
    if ([bundle isLoaded] == false) [bundle load];//調(diào)用bunlde加載接口加載,bundle表示一個(gè)包含代碼、資源和其他文件的目錄或者是一個(gè).framework文件

    //UnityFramework類的頭文件是UnityFramework.h,實(shí)現(xiàn)文件在Classes文件夾中的main.mm
    UnityFramework* ufw = [bundle.principalClass getInstance];//獲取bundle主類示例,主類是一個(gè)UnityFramework,bundle 只有一個(gè)主類,該類通常是應(yīng)用程序的控制器類
    if (![ufw appController])  //調(diào)用appController方法獲取,第一次獲取的為空                  
    {
        // unity is not initialized
        [ufw setExecuteHeader: &_mh_execute_header];//設(shè)置頭信息,初始化unity引擎
    }
    return ufw;
}

int main(int argc, char* argv[])//main是整個(gè)應(yīng)用程序的入口,和什么語言沒關(guān)系,一般都是這樣
{
    @autoreleasepool //創(chuàng)建一個(gè)自動(dòng)釋放池
    {
        id ufw = UnityFrameworkLoad();//先加載了UnityFramework
        [ufw runUIApplicationMainWithArgc: argc argv: argv];//runUIApplicationMainWithArgc,這個(gè)方式是UnityFramework.h中的方法
        return 0;
    }
}

可以看看UnityFramework.h文件中定義的函數(shù)

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>

#import "UnityAppController.h"

#include "UndefinePlatforms.h"
#include <mach-o/ldsyms.h>
typedef struct
#ifdef __LP64__
    mach_header_64
#else
    mach_header
#endif
    MachHeader;
#include "RedefinePlatforms.h"


//! Project version number for UnityFramework.
FOUNDATION_EXPORT double UnityFrameworkVersionNumber;

//! Project version string for UnityFramework.
FOUNDATION_EXPORT const unsigned char UnityFrameworkVersionString[];

// In this header, you should import all the public headers of your framework using statements like #import <UnityFramework/PublicHeader.h>

#pragma once

// important app life-cycle events
__attribute__ ((visibility("default")))
@protocol UnityFrameworkListener<NSObject>
@optional
- (void)unityDidUnload:(NSNotification*)notification;
- (void)unityDidQuit:(NSNotification*)notification;
@end

__attribute__ ((visibility("default")))
@interface UnityFramework : NSObject
{
}

- (UnityAppController*)appController;

+ (UnityFramework*)getInstance;

- (void)setDataBundleId:(const char*)bundleId;

- (void)runUIApplicationMainWithArgc:(int)argc argv:(char*[])argv;
- (void)runEmbeddedWithArgc:(int)argc argv:(char*[])argv appLaunchOpts:(NSDictionary*)appLaunchOpts;

- (void)unloadApplication;
- (void)quitApplication:(int)exitCode;

- (void)registerFrameworkListener:(id<UnityFrameworkListener>)obj;
- (void)unregisterFrameworkListener:(id<UnityFrameworkListener>)obj;

- (void)showUnityWindow;
- (void)pause:(bool)pause;

- (void)setExecuteHeader:(const MachHeader*)header;
- (void)sendMessageToGOWithName:(const char*)goName functionName:(const char*)name message:(const char*)msg;

@end

函數(shù)實(shí)現(xiàn)在Classes文件夾下的main.mm文件中

#include "RegisterFeatures.h"
#include <csignal>
#include "UnityInterface.h"
#include "../UnityFramework/UnityFramework.h"

void UnityInitTrampoline();

// WARNING: this MUST be c decl (NSString ctor will be called after +load, so we cant really change its value)
const char* AppControllerClassName = "UnityAppController";

#if UNITY_USES_DYNAMIC_PLAYER_LIB
extern "C" void SetAllUnityFunctionsForDynamicPlayerLib();
#endif

extern "C" void UnitySetExecuteMachHeader(const MachHeader* header);

extern "C" __attribute__((visibility("default"))) NSString* const kUnityDidUnload;
extern "C" __attribute__((visibility("default"))) NSString* const kUnityDidQuit;

@implementation UnityFramework
{
    int runCount;
}

UnityFramework* _gUnityFramework = nil;
+ (UnityFramework*)getInstance 
{
    if (_gUnityFramework == nil)
    {
        _gUnityFramework = [[UnityFramework alloc] init];//獲取單例時(shí)先調(diào)用alloc分配內(nèi)存,再調(diào)用init初始化
    }
    return _gUnityFramework;
}

- (UnityAppController*)appController
{
    return GetAppController(); //調(diào)用UnityAppController.mm中的方法
}

- (void)setExecuteHeader:(const MachHeader*)header
{
    UnitySetExecuteMachHeader(header);//一個(gè) Unity 引擎的函數(shù),用于設(shè)置當(dāng)前可執(zhí)行文件的 Mach-O 頭信息,header是一個(gè)指向可執(zhí)行文件 Mach-O 頭信息的指針
}//在 macOS 或 iOS 上,可執(zhí)行文件的 Mach-O 頭信息包含有關(guān)可執(zhí)行文件的元數(shù)據(jù),例如文件類型、CPU 架構(gòu)、入口點(diǎn)和段信息。Unity 引擎使用該函數(shù)來設(shè)置當(dāng)前可執(zhí)行文件的 Mach-O 頭信息,以確保 Unity 引擎可以正確加載并執(zhí)行游戲邏輯。

- (void)sendMessageToGOWithName:(const char*)goName functionName:(const char*)name message:(const char*)msg
{
    UnitySendMessage(goName, name, msg);
}

- (void)registerFrameworkListener:(id<UnityFrameworkListener>)obj
{
#define REGISTER_SELECTOR(sel, notif_name)                  \
if([obj respondsToSelector:sel])                        \
[[NSNotificationCenter defaultCenter]   addObserver:obj selector:sel name:notif_name object:nil];

    REGISTER_SELECTOR(@selector(unityDidUnload:), kUnityDidUnload);
    REGISTER_SELECTOR(@selector(unityDidQuit:), kUnityDidQuit);

#undef REGISTER_SELECTOR
}

- (void)unregisterFrameworkListener:(id<UnityFrameworkListener>)obj
{
    [[NSNotificationCenter defaultCenter] removeObserver: obj name: kUnityDidUnload object: nil];
    [[NSNotificationCenter defaultCenter] removeObserver: obj name: kUnityDidQuit object: nil];
}

- (void)frameworkWarmup:(int)argc argv:(char*[])argv
{
#if UNITY_USES_DYNAMIC_PLAYER_LIB
    SetAllUnityFunctionsForDynamicPlayerLib();
#endif


    UnityInitTrampoline();
    UnityInitRuntime(argc, argv);

    RegisterFeatures();

    // iOS terminates open sockets when an application enters background mode.
    // The next write to any of such socket causes SIGPIPE signal being raised,
    // even if the request has been done from scripting side. This disables the
    // signal and allows Mono to throw a proper C# exception.
    std::signal(SIGPIPE, SIG_IGN);
}

- (void)setDataBundleId:(const char*)bundleId
{
    UnitySetDataBundleDirWithBundleId(bundleId);
}

- (void)runUIApplicationMainWithArgc:(int)argc argv:(char*[])argv
{
    self->runCount += 1;
    [self frameworkWarmup: argc argv: argv];
    UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String: AppControllerClassName]);
    //UIApplicationMain是iOS應(yīng)用程序的入口點(diǎn),一般在入口main函數(shù)中調(diào)用,unity在frameworkWarmup后調(diào)用,其用于啟動(dòng)應(yīng)用程序并設(shè)置應(yīng)用程序的主運(yùn)行循環(huán)(main run loop)
    //該方法有4個(gè)參數(shù),第三個(gè)參數(shù)是NSString類型的principalClassName,其是應(yīng)用程序?qū)ο笏鶎俚念悾擃惐仨毨^承自UIApplication類,如果所屬類字符串的值為nil, UIKit就缺省使用UIApplication類
    //第四個(gè)參數(shù)是NSString類型的delegateClassName,其是應(yīng)用程序類的代理類,該函數(shù)跟據(jù)delegateClassName創(chuàng)建一個(gè)delegate對(duì)象,并將UIApplication對(duì)象中的delegate屬性設(shè)置為delegate對(duì)象,這里創(chuàng)建了UnityAppController,看其頭文件是繼承了UIApplicationDelegate
    //該函數(shù)創(chuàng)建UIApplication對(duì)象和AppDelegate對(duì)象,然后將控制權(quán)交給主運(yùn)行循環(huán),等待事件的發(fā)生。UIApplicationMain還會(huì)創(chuàng)建應(yīng)用程序的主窗口,并將其顯示在屏幕上,從而啟動(dòng)應(yīng)用程序的UI界面。
}

- (void)runEmbeddedWithArgc:(int)argc argv:(char*[])argv appLaunchOpts:(NSDictionary*)appLaunchOpts
{
    if (self->runCount)
    {
        // initialize from partial unload ( sceneLessMode & onPause )
        UnityLoadApplicationFromSceneLessState();
        UnitySuppressPauseMessage();
        [self pause: false];
        [self showUnityWindow];

        // Send Unity start event
        UnitySendEmbeddedLaunchEvent(0);
    }
    else
    {
        // full initialization from ground up
        [self frameworkWarmup: argc argv: argv];

        id app = [UIApplication sharedApplication];

        id appCtrl = [[NSClassFromString([NSString stringWithUTF8String: AppControllerClassName]) alloc] init];
        [appCtrl application: app didFinishLaunchingWithOptions: appLaunchOpts];

        [appCtrl applicationWillEnterForeground: app];
        [appCtrl applicationDidBecomeActive: app];

        // Send Unity start (first time) event
        UnitySendEmbeddedLaunchEvent(1);
    }

    self->runCount += 1;
}

- (void)unloadApplication
{
    UnityUnloadApplication();
}

- (void)quitApplication:(int)exitCode
{
    UnityQuitApplication(exitCode);
}

- (void)showUnityWindow
{
    [[[self appController] window] makeKeyAndVisible];
}

- (void)pause:(bool)pause
{
    UnityPause(pause);
}

@end


#if TARGET_IPHONE_SIMULATOR && TARGET_TVOS_SIMULATOR
#include <pthread.h>

extern "C" int pthread_cond_init$UNIX2003(pthread_cond_t *cond, const pthread_condattr_t *attr)
{ return pthread_cond_init(cond, attr); }
extern "C" int pthread_cond_destroy$UNIX2003(pthread_cond_t *cond)
{ return pthread_cond_destroy(cond); }
extern "C" int pthread_cond_wait$UNIX2003(pthread_cond_t *cond, pthread_mutex_t *mutex)
{ return pthread_cond_wait(cond, mutex); }
extern "C" int pthread_cond_timedwait$UNIX2003(pthread_cond_t *cond, pthread_mutex_t *mutex,
    const struct timespec *abstime)
{ return pthread_cond_timedwait(cond, mutex, abstime); }

#endif // TARGET_IPHONE_SIMULATOR && TARGET_TVOS_SIMULATOR

調(diào)用UIApplicationMain創(chuàng)建了UnityAppController之后,接收iOS系統(tǒng)事件通知即可,接收通知的處理在?UnityAppController.mm文件中。下面是與生命周期相關(guān)的事件

先是willFinishLaunchingWithOptions,只發(fā)了個(gè)通知

- (BOOL)application:(UIApplication*)application willFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
    AppController_SendNotificationWithArg(kUnityWillFinishLaunchingWithOptions, launchOptions);
    return YES;
}

void AppController_SendNotificationWithArg(NSString* name, id arg) //Unity引擎用于在iOS平臺(tái)上發(fā)送消息通知的方法
{
    [[NSNotificationCenter defaultCenter] postNotificationName: name object: GetAppController() userInfo: arg];
}

隨后是didFinishLaunchingWithOptions

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
    ::printf("-> applicationDidFinishLaunching()\n");

    // send notfications
#if !PLATFORM_TVOS

    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wdeprecated-declarations"

    if (UILocalNotification* notification = [launchOptions objectForKey: UIApplicationLaunchOptionsLocalNotificationKey])
        UnitySendLocalNotification(notification);

    if ([UIDevice currentDevice].generatesDeviceOrientationNotifications == NO)
        [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];

    #pragma clang diagnostic pop

#endif
    //UnityDataBundleDir()是一個(gè)用于獲取Unity數(shù)據(jù)包目錄的方法,它返回一個(gè)NSString對(duì)象,表示Unity數(shù)據(jù)包的路徑
    //隨后初始化Unity應(yīng)用程序,但不會(huì)創(chuàng)建圖形界面
    UnityInitApplicationNoGraphics(UnityDataBundleDir());

    [self selectRenderingAPI];//在iOS平臺(tái)上,Unity引擎通常支持OpenGL ES和Metal兩種渲染API,該方法會(huì)根據(jù)具體的設(shè)備和系統(tǒng)版本等因素來動(dòng)態(tài)地選擇使用哪種渲染API
    [UnityRenderingView InitializeForAPI: self.renderingAPI];//UnityRenderingView是用于呈現(xiàn)Unity引擎場(chǎng)景的iOS視圖,InitializeForAPI是UnityRenderingView的初始化方法,self.renderingAPI表示Unity引擎所選的渲染API

#if (PLATFORM_IOS && defined(__IPHONE_13_0)) || (PLATFORM_TVOS && defined(__TVOS_13_0))
    if (@available(iOS 13, tvOS 13, *))
        _window = [[UIWindow alloc] initWithWindowScene: [self pickStartupWindowScene: application.connectedScenes]];
    else
#endif
//UIWindow是iOS中的一個(gè)視圖對(duì)象,用于展示應(yīng)用程序的用戶界面.它是一個(gè)特殊的視圖,通常作為應(yīng)用程序中所有視圖的容器。在iOS中,每個(gè)應(yīng)用程序都有一個(gè)主窗口,即UIWindow對(duì)象,它是整個(gè)應(yīng)用程序界面的根視圖。所有其他的視圖都是添加到UIWindow對(duì)象中的。
//UIWindow對(duì)象還可以響應(yīng)用戶的觸摸事件和手勢(shì),同Android一樣,Untiy會(huì)自己渲染視圖,但需要使用操作系統(tǒng)提供的觸摸事件
    _window = [[UIWindow alloc] initWithFrame: [UIScreen mainScreen].bounds];
//創(chuàng)建UnityRenderingView對(duì)象,而不是使用iOS系統(tǒng)的視圖對(duì)象,如UIView或UIWindow,這個(gè)視圖對(duì)象會(huì)放入U(xiǎn)IWindow中
    _unityView = [self createUnityView];


    [DisplayManager Initialize];//unity的顯示器管理類初始化,unity使用DisplayManager來管理顯示器并在多個(gè)顯示器上呈現(xiàn)Unity場(chǎng)景
    _mainDisplay = [DisplayManager Instance].mainDisplay;//設(shè)置主顯示器
    [_mainDisplay createWithWindow: _window andView: _unityView];//將iOS的窗口UIWindow和Unity的RenderingView同主顯示器關(guān)聯(lián)起來

    [self createUI];//用于創(chuàng)建iOS應(yīng)用程序界面中的常規(guī)視圖對(duì)象,例如按鈕、標(biāo)簽、文本框等
    [self preStartUnity];//預(yù)啟動(dòng),在unity啟動(dòng)前可以注冊(cè)插件

    // if you wont use keyboard you may comment it out at save some memory
    [KeyboardDelegate Initialize];

    return YES;
}

之后是applicationDidBecomeActive

- (void)applicationDidBecomeActive:(UIApplication*)application
{
    ::printf("-> applicationDidBecomeActive()\n");

    [self removeSnapshotViewController];//刪除iOS應(yīng)用程序窗口中的快照視圖控制器
    //在iOS應(yīng)用程序中,當(dāng)應(yīng)用程序進(jìn)入后臺(tái)時(shí),系統(tǒng)會(huì)自動(dòng)截取當(dāng)前應(yīng)用程序的截圖,以便在應(yīng)用程序再次進(jìn)入前臺(tái)時(shí)快速還原應(yīng)用程序的狀態(tài)。\
    //這個(gè)截圖被稱為快照(Snapshot),而用于管理快照的視圖控制器被稱為快照視圖控制器(Snapshot View Controller)
    //unity自己渲染畫面,不需要

    if (_unityAppReady)//從后臺(tái)切換到前臺(tái)時(shí)
    {
        if (UnityIsPaused() && _wasPausedExternal == false)
        {
            UnityWillResume();//會(huì)調(diào)用OnApplicaionFous
            UnityPause(0);
        }
        if (_wasPausedExternal)
        {
            if (UnityIsFullScreenPlaying())
                TryResumeFullScreenVideo();
        }
        // need to do this with delay because FMOD restarts audio in AVAudioSessionInterruptionNotification handler
        [self performSelector: @selector(updateUnityAudioOutput) withObject: nil afterDelay: 0.1];
        UnitySetPlayerFocus(1);
    }
    else if (!_startUnityScheduled)//剛打開游戲app走這里,調(diào)用startUnity
    {
        _startUnityScheduled = true;
        [self performSelector: @selector(startUnity:) withObject: application afterDelay: 0];
    }

    _didResignActive = false;
}

- (void)startUnity:(UIApplication*)application
{
    NSAssert(_unityAppReady == NO, @"[UnityAppController startUnity:] called after Unity has been initialized");

    UnityInitApplicationGraphics();//初始化Unity引擎的圖形渲染

    // we make sure that first level gets correct display list and orientation
    [[DisplayManager Instance] updateDisplayListCacheInUnity];

    UnityLoadApplication();
    Profiler_InitProfiler();//初始化Profiler

    [self showGameUI];
    [self createDisplayLink];

    UnitySetPlayerFocus(1);

    AVAudioSession* audioSession = [AVAudioSession sharedInstance];
    [audioSession setCategory: AVAudioSessionCategoryAmbient error: nil];
    if (UnityIsAudioManagerAvailableAndEnabled())
    {
        if (UnityShouldPrepareForIOSRecording())
        {
            [audioSession setCategory: AVAudioSessionCategoryPlayAndRecord error: nil];
        }
        else if (UnityShouldMuteOtherAudioSources())
        {
            [audioSession setCategory: AVAudioSessionCategorySoloAmbient error: nil];
        }
    }

    [audioSession setActive: YES error: nil];
    [audioSession addObserver: self forKeyPath: @"outputVolume" options: 0 context: nil];
    UnityUpdateMuteState([audioSession outputVolume] < 0.01f ? 1 : 0);

#if UNITY_REPLAY_KIT_AVAILABLE
    void InitUnityReplayKit();  // Classes/Unity/UnityReplayKit.mm

    InitUnityReplayKit();
#endif
}

再后是進(jìn)入后臺(tái)進(jìn)入前臺(tái)

- (void)applicationDidEnterBackground:(UIApplication*)application
{
    ::printf("-> applicationDidEnterBackground()\n");
}

- (void)applicationWillEnterForeground:(UIApplication*)application
{
    ::printf("-> applicationWillEnterForeground()\n");

    // applicationWillEnterForeground: might sometimes arrive *before* actually initing unity (e.g. locking on startup)
    if (_unityAppReady)
    {
        // if we were showing video before going to background - the view size may be changed while we are in background
        [GetAppController().unityView recreateRenderingSurfaceIfNeeded];
    }
}

最后是applicationWillResignActive

- (void)applicationWillResignActive:(UIApplication*)application
{
    ::printf("-> applicationWillResignActive()\n");

    if (_unityAppReady)
    {
        UnitySetPlayerFocus(0);

        // signal unity that the frame rendering have ended
        // as we will not get the callback from the display link current frame
        UnityDisplayLinkCallback(0);

        _wasPausedExternal = UnityIsPaused();
        if (_wasPausedExternal == false)
        {
            // Pause Unity only if we don't need special background processing
            // otherwise batched player loop can be called to run user scripts.
            if (!UnityGetUseCustomAppBackgroundBehavior())
            {
#if UNITY_SNAPSHOT_VIEW_ON_APPLICATION_PAUSE
                // Force player to do one more frame, so scripts get a chance to render custom screen for minimized app in task manager.
                // NB: UnityWillPause will schedule OnApplicationPause message, which will be sent normally inside repaint (unity player loop)
                // NB: We will actually pause after the loop (when calling UnityPause).
                UnityWillPause();
                [self repaint];
                UnityWaitForFrame();

                [self addSnapshotViewController];
#endif
                UnityPause(1);
            }
        }
    }

    _didResignActive = true;
}

【接入SDK】

總體上和Android沒什么區(qū)別,相比Andorid好點(diǎn)是不用做Jar,因?yàn)楸举|(zhì)上是C#調(diào)用C,C調(diào)用OC,一些需要的編譯在出包的時(shí)候都會(huì)編譯好。

同樣的看是否需要生命周期,不需要生命周期的自己寫調(diào)用即可。如果需要生命周期,同樣是需要繼承的,在Android中繼承的是Activiry,在iOS就是要繼承UnityAppController。

在Plugins/iOS路徑下創(chuàng)建CustomAppController.mm?文件。(文件名必須是 ___AppController,前綴可自選,但不能省略;否則在 Build 項(xiàng)目的時(shí)候,會(huì)被移動(dòng)到錯(cuò)誤的目錄中去。)文件主要代碼如下:



@interface CustomAppController : UnityAppController

@end

IMPL_APP_CONTROLLER_SUBCLASS (CustomAppController)
@implementation CustomAppController


//重寫生命周期函數(shù)
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
    [super application:application didFinishLaunchingWithOptions:launchOptions];
    //自己的代碼
    return YES;
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    
    [super applicationDidBecomeActive:appliction]
    //自己的代碼
}

//其他生命周期函數(shù)

@end

在Build iOS Project時(shí),Unity會(huì)自動(dòng)把該文件復(fù)制到Library文件里,原來的 UnityAppController在Classes文件夾里。

通過IMPL_APP_CONTROLLER_SUBCLASS知道要使用我們定制的 CustomAppController 而不是使用默認(rèn)的 UnityAppController,其定義在UnityAppController.h文件中??梢钥吹狡渥饔檬窃趌oad的時(shí)候修改了AppControllerClassName。也即在加載UnityFramework時(shí)替換名字,這樣在創(chuàng)建UIApplicationMain中創(chuàng)建的是我們新建的AppController。

// Put this into mm file with your subclass implementation
// pass subclass name to define

#define IMPL_APP_CONTROLLER_SUBCLASS(ClassName) \
@interface ClassName(OverrideAppDelegate)       \
{                                               \
}                                               \
+(void)load;                                    \
@end                                            \
@implementation ClassName(OverrideAppDelegate)  \
+(void)load                                     \
{                                               \
    extern const char* AppControllerClassName;  \
    AppControllerClassName = #ClassName;        \
}                                               \
@end   

【參考】

UnityAppController的定制以及Unity引擎的IL2CPP機(jī) - 簡書文章來源地址http://www.zghlxwxcb.cn/news/detail-548191.html

到了這里,關(guān)于Unity與iOS交互(2)——接入SDK的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Kotlin & Compose Multiplatform 跨平臺(tái)開發(fā)實(shí)踐之加入 iOS 支持

    Kotlin & Compose Multiplatform 跨平臺(tái)開發(fā)實(shí)踐之加入 iOS 支持

    幾個(gè)月前 Compose Multiplatform 的 iOS 支持就宣布進(jìn)入了 Alpha 階段,這意味著它已經(jīng)具備了一定的可用性。 在它發(fā)布 Alpha 的時(shí)候,我就第一時(shí)間嘗鮮,但是只是淺嘗輒止,沒有做過多的探索,最近恰好有點(diǎn)時(shí)間,于是我又重新開始學(xué)習(xí) Compose Multiplatform ,并且嘗試移植我已有的項(xiàng)

    2024年02月07日
    瀏覽(25)
  • 【HarmonyOS開發(fā)】ArkUI-X 跨平臺(tái)框架(使用ArkTs開發(fā)Android&IOS)

    【HarmonyOS開發(fā)】ArkUI-X 跨平臺(tái)框架(使用ArkTs開發(fā)Android&IOS)

    ArkUI-X 跨平臺(tái)框架進(jìn)一步將 ArkUI 開發(fā)框架擴(kuò)展到了多個(gè)OS平臺(tái),目前支持OpenHarmony、HarmonyOS、Android、 iOS,后續(xù)會(huì)逐步增加更多平臺(tái)支持。開發(fā)者基于一套主代碼,就可以構(gòu)建支持多平臺(tái)的精美、高性能應(yīng)用。 React Native 是一個(gè)基于 JavaScript 和 React 的開源框架,由 Facebook 開發(fā)和

    2024年01月20日
    瀏覽(27)
  • 滾動(dòng)條詳解:跨平臺(tái)iOS、Android、小程序滾動(dòng)條隱藏及自定義樣式綜合指南

    滾動(dòng)條詳解:跨平臺(tái)iOS、Android、小程序滾動(dòng)條隱藏及自定義樣式綜合指南

    滾動(dòng)條是用戶界面中的圖形化組件,用于指示和控制內(nèi)容區(qū)域的可滾動(dòng)范圍。當(dāng)元素內(nèi)容超出其視窗邊界時(shí),滾動(dòng)條提供可視化線索,并允許用戶通過鼠標(biāo)滾輪、觸屏滑動(dòng)或直接拖動(dòng)滑塊來瀏覽未顯示部分,實(shí)現(xiàn)內(nèi)容的上下或左右滾動(dòng)。它在保持界面整潔、避免內(nèi)容溢出的同

    2024年04月27日
    瀏覽(25)
  • Unity跨平臺(tái)開發(fā)指南(PC/VR/Android/WebGL)

    Unity跨平臺(tái)開發(fā)指南(PC/VR/Android/WebGL)

    通常我在進(jìn)行不同平臺(tái)的設(shè)置時(shí)會(huì)基于以下幾點(diǎn): 1:創(chuàng)建、開發(fā)、打包時(shí)我們通常針對(duì)Player和Quality設(shè)置進(jìn)行質(zhì)量的設(shè)定 2:在不同平臺(tái)上運(yùn)行時(shí),有不同的平臺(tái)包體大小,加載方式的限定,測(cè)試、打包上的區(qū)別,幀率穩(wěn)定60 3:代碼封裝上的區(qū)別,特別針對(duì)單一項(xiàng)目轉(zhuǎn)為不同

    2024年01月21日
    瀏覽(29)
  • 【LocalSend】開源跨平臺(tái)的局域網(wǎng)文件傳輸工具,支持IOS、Android、Mac、Windows、Linux

    【LocalSend】開源跨平臺(tái)的局域網(wǎng)文件傳輸工具,支持IOS、Android、Mac、Windows、Linux

    工作前提條件:設(shè)備使用相同的局域網(wǎng)。 LocalSend is a cross-platform app that enables secure communication between devices using a REST API and HTTPS encryption. Unlike other messaging apps that rely on external servers, LocalSend doesn’t require an internet connection or third-party servers, making it a fast and reliable solution for local

    2024年02月17日
    瀏覽(92)
  • Unity跨平臺(tái)UI解決方案:可能是最全的FairyGUI系列教程

    Unity跨平臺(tái)UI解決方案:可能是最全的FairyGUI系列教程

    FairyGUI的項(xiàng)目文件結(jié)構(gòu) .objs 內(nèi)部數(shù)據(jù)目錄。注意:不要加入版本管理,因?yàn)檫@里的內(nèi)容是不需要共享的。 assets 包內(nèi)容放置目錄,資源內(nèi)容都在這里面,里面還可以分不同的包,便于區(qū)分管理(看下圖) settings 配置文件放置目錄。 ****.fairy 項(xiàng)目識(shí)別文件,也就是項(xiàng)目名稱 目錄

    2024年04月14日
    瀏覽(102)
  • 跨平臺(tái)應(yīng)用開發(fā)進(jìn)階(五十)uni-app ios web-view嵌套H5項(xiàng)目白屏問題分析及解決

    跨平臺(tái)應(yīng)用開發(fā)進(jìn)階(五十)uni-app ios web-view嵌套H5項(xiàng)目白屏問題分析及解決

    應(yīng)用 uni-app 框架開發(fā)好APP上架使用過程中,發(fā)現(xiàn)應(yīng)用經(jīng)過長時(shí)間由后臺(tái)切換至前臺(tái)時(shí),通過 webview 方式嵌套的H5頁面發(fā)生白屏現(xiàn)象。 任何手機(jī)設(shè)備上,當(dāng)手機(jī)內(nèi)存不足時(shí),os都會(huì)回收資源。一般是先回收后臺(tái)打開的資源。如果當(dāng)前應(yīng)用占用的資源過高,當(dāng)前應(yīng)用也有可能崩潰

    2024年02月14日
    瀏覽(24)
  • Unity與Android交互(4)——接入SDK

    Unity與Android交互(4)——接入SDK

    【前言】 unity接入Android SDK有兩種方式,一種是把Unity的工程導(dǎo)出google project的形式進(jìn)行接入,另一種是通過把Android的工程做成Plugins的形式進(jìn)行接入。我們接入SDK基本都是將SDK作為插件的形式接入的。 對(duì)我們接入SDK的人來說,SDK也是分等級(jí)的: 第一等級(jí):只有so文件,這種

    2024年02月16日
    瀏覽(25)
  • Unity下實(shí)現(xiàn)跨平臺(tái)的RTMP推流|輕量級(jí)RTSP服務(wù)|RTMP播放|RTSP播放低延遲解決方案

    Unity下實(shí)現(xiàn)跨平臺(tái)的RTMP推流|輕量級(jí)RTSP服務(wù)|RTMP播放|RTSP播放低延遲解決方案

    2018年,我們開始在原生RTSP|RTMP直播播放器的基礎(chǔ)上,對(duì)接了Unity環(huán)境下的低延遲播放,毫秒級(jí)延遲,發(fā)布后,就得到了業(yè)內(nèi)一致的認(rèn)可。然后我們覆蓋了Windows、Android、iOS、Linux的RTMP推送、輕量級(jí)RTSP服務(wù)和RTSP|RTMP播放。 目前看,Unity環(huán)境下,我們?cè)谛袠I(yè)內(nèi)的延遲幾乎是最低的

    2024年01月22日
    瀏覽(22)
  • 【QT+QGIS跨平臺(tái)編譯】之七:【libjpeg+Qt跨平臺(tái)編譯】(一套代碼、一套框架,跨平臺(tái)編譯)

    【QT+QGIS跨平臺(tái)編譯】之七:【libjpeg+Qt跨平臺(tái)編譯】(一套代碼、一套框架,跨平臺(tái)編譯)

    libjpeg是一個(gè)廣泛使用的jpeg圖像壓縮和解壓的函數(shù)庫,采用 C 語言開發(fā)。 2013年1月,Independent JPEG Group發(fā)布了版本9,對(duì)新引入的無損編碼模式進(jìn)行了改進(jìn)。2022年1月,發(fā)布了版本9e,是唯一真正的源參考JPEG編解碼器。 【libjpeg跨平臺(tái)編譯】:Windows環(huán)境下編譯成果(支撐QGIS跨平臺(tái)

    2024年01月25日
    瀏覽(97)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包