3D touch在Unity3D中的使用


0、開篇:

     3D touch隨着iOS9發布,它並不是一個單獨的技術,而是可以分為pressure sensitivity、quick action以及peek&pop。在官方的介紹中提到可以給游戲更好的體驗,但是實際上個人感覺除了pressure sensitivity能夠改變游戲的操作方式外,quick action以及peek&pop真心是為APP設計的。

1、pressure sensitivity的使用:

    首先在unity的腳本中添加檢查是否支持3D touch的函數,這個函數本質是調用iOS代碼的。

 [DllImport("__Internal")]
    // return 1 when device is support 3d touch
    private static extern int _checkForceTouchCapability();

 public static int CheckForceTouchCapability()
    {
        return _checkForceTouchCapability();
    }

對應的iOS代碼為

-(NSInteger)CheckForceTouchCapability
{
    if ([[[UIDevice currentDevice] systemVersion] floatValue] < 9.0) {
        isSupport3DTouch = NO;
        return 0;
    }
    if(self.rootViewController.view.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
    {
        isSupport3DTouch = YES;
        return 1;
    } else {
        isSupport3DTouch = NO;
        return 0;
    }
}

下面是響應壓力變化的處理函數,這次用傳遞函數指針到oc代碼的方式來做,當然你也可以在iOS中使用UnitySendMessage方法。

private delegate void touch_event_callback_delegate(float force, float maximumPossibleForce);

private static Action<float, float> touchEventCallback;

[DllImport("__Internal")]
private static extern void _registTouchEventCallback(touch_event_callback_delegate func);

public static void RegistTouchEventCallback(Action<float, float> func)
    {
        touchEventCallback = func;
        _registTouchEventCallback(ExecuteTouchEventCallback);
    }

[MonoPInvokeCallback(typeof(touch_event_callback_delegate))]
private static void ExecuteTouchEventCallback(float force, float maximumPossibleForce)
    {
        touchEventCallback(force, maximumPossibleForce);
    }

對應的iOS代碼為

typedef void (*registTouchEventCallbackFunc)(float, float);

static registTouchEventCallbackFunc touchEventCallback = nil;

-(void)registTouchEventCallback:(registTouchEventCallbackFunc) func
{
    touchEventCallback = func;
}

unity生成的Xcode工程中有個UnityView.mm文件,為了能夠獲取iOS中的壓力變化,需要修改一下的代碼

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
    UnitySendTouchesBegin(touches, event);
    [UnityAppController UpdateForce:touches];
}
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
    UnitySendTouchesEnded(touches, event);
    [UnityAppController TouchesEndorCancelled:touches];
}
- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event
{
    UnitySendTouchesCancelled(touches, event);
    [UnityAppController TouchesEndorCancelled:touches];
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
    UnitySendTouchesMoved(touches, event);
    [UnityAppController UpdateForce:touches];
}
UpdateForce和TouchesEndorCancelled的定義為:
/**
 *  實時反饋壓感
 *
 *  @param touches touch數據
 */
+(void)UpdateForce:(NSSet<UITouch *>*) touches
{
    if (isSupport3DTouch && touchEventCallback != nil) {
        touchEventCallback(touches.anyObject.force, touches.anyObject.maximumPossibleForce);
    }
    
}

/**
 *  touchesEnded或者touchesCancelled觸發時的處理
 */
+(void)TouchesEndorCancelled:(NSSet<UITouch *>*) touches
{
    if (isSupport3DTouch && touchEventCallback != nil) {
        touchEventCallback(0, touches.anyObject.maximumPossibleForce);
    }
}

其實用UnitySendMessage是最簡單的,在TouchesEndorCancelled中force直接賦值為0的原因是我在測試的過程中發現快速的點擊並且離開屏幕有時拿到的force不是0,這樣在游戲中使用這個力的時候會有問題。

2、quick action的應用

   目前想到的就是快速進入某個游戲場景吧,或者進入游戲后直接開啟某個UI,總之對游戲性上沒啥幫助。我在Demo中做的是快速進入場景2,默認應該是進入場景1。首先需要在info.plist中進行設置:

<key>UIApplicationShortcutItems</key>
    <array>
        <dict>
            <key>UIApplicationShortcutItemIconType</key>
            <string>UIApplicationShortcutIconTypePlay</string>
            <key>UIApplicationShortcutItemTitle</key>
            <string>JUMP TO SCENE 2</string>
            <key>UIApplicationShortcutItemType</key>
            <string>$(PRODUCT_BUNDLE_IDENTIFIER).action</string>
            <key>UIApplicationShortcutItemUserInfo</key>
            <dict>
                <key>scene</key>
                <string>2</string>
            </dict>
        </dict>
    </array>

核心是設置UIApplicationShortcutItemUserInfo,因為我們拿到的參數是從userinfo中拿到的。在使用quick action時unity中的編程非常少,主要是iOS編程。

首先需要在UnityAppcontroller.mm中添加:

- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL succeeded)) completionHandler {
    BOOL bHandledShortCutItem = [self handleShortCutItem:shortcutItem];
    completionHandler(bHandledShortCutItem);
}

-(BOOL)handleShortCutItem:(UIApplicationShortcutItem*) shortcutItem
{
    BOOL handled = NO;
    NSString *str = (NSString *)[shortcutItem.userInfo objectForKey:@"scene"];
    if (str != nil) {
        handled = YES;
        UnitySendMessage("Interface", "ExecuteQuickAction", [str UTF8String]);
    }
    
    return handled;
}

這個系統方法是用於處理在screen使用quick action進入游戲的。看了很多別人寫的例子,在didFinishLaunchingWithOptions中會調用handleShortCutItem,然后返回NO,這樣可以避免performActionForShortcutItem的調用。但是實際在測試中發現完全不需要在didFinishLaunchingWithOptions中會調用handleShortCutItem。

 

3、peek&pop

     完全沒有想到怎么用到游戲中,而且發現在peek時會有一個模糊的遮罩層。

4、Demo地址:https://github.com/klkucan/Unity_For3DTouch

 

 

 

 

     


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM