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




补充:

由于pressure sensitivity最后需要修改UnityView.mm文件,而UnityView.mm是每次打包都会冲掉的,所以需要在不修改UnityView.mm的前提下完成功能。所以就新建了个CustomUnityView,继承UnityView,

#import <Foundation/Foundation.h>
#import <Classes/UI/UnityView.h>
@interface CustomUnityView : UnityView
{
}
@end
然后在CustomUnityViewchongx

#import "UnityAppController+For3DTouch.h"
#import "CustomUnityView.h"

@implementation CustomUnityView

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
	[super touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event];
    [UnityAppController UpdateForce:touches];
}
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
	[super touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event];
    [UnityAppController TouchesEndorCancelled:touches];
}
- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event
{
	[super touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event];
    [UnityAppController TouchesEndorCancelled:touches];
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
	[super touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event];
    [UnityAppController UpdateForce:touches];
}

@end


然后在CustomUnityAppController.mm中重写createUnityView函数

- (UnityView*)createUnityView
{
    return [[CustomUnityView alloc] initFromMainScreen];
}


CustomUnityView.h和CustomUnityView.mm放到unity下面的Plugins\iOS


©️2020 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值