Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
4
Help us understand the problem. What is going on with this article?
@fuziki

キーボードとして動作するコントローラのUnityのNative Pluginを作る

More than 1 year has passed since last update.

はじめに

良さげなコントローラのUnityのNative Pluginを作りました。

環境

目的

良さげなコントローラがあったので、Unityで使ってみる
持ちやすくて、操作がしやすそうなコントローラがあったので、Unityで使いたいなと思いました。
という訳で、とりあえずBluetooth接続したら、こう↓でした。

という訳で、今回の目的がこちら
良さげなコントローラがあったので、Unityで使ってみる

UnityのiOSアプリで、キーボードを出さずに、キーボードの入力を受け取る

UnityのiOSアプリで、キーボードを出さずに、キーボードの入力を受け取る

試したこと

TouchScreenKeyboard.hideInput

TouchScreenKeyboard.hideInputを使って、キーボードを非表示にしてキー入力を受け取る
→失敗
※類似APIも期待した動作になりませんでした、、、

UIResponder.keyCommands

UIResponder.keyCommandsにUIKeyCommandを使って、キー入力を受け取る。
→成功

コントローラの入力を解析する

input On Press On Release
JoyStick.up w e
JoyStick.Right d c
JoyStick.Down x z
JoyStick.Left a q
Button.A u f
Button.B h r
Button.C y t
Button.D j n
Trigger.Return l v
Trigger.OK o g

→これらの入力を検出し、通知することで、コントローラとして利用できる

UIResponder.keyCommands

UIResponder.keyCommandsを設定する

キー入力を受け取る度に、keyCommandsが探索され、入力の組み合わせと合致するkeyCommandsを設定したUIKeyCommandのactionに通知されます。
mapを使って文字列からUIKeyCommand配列を作っています。

ViewController.swift
    override var keyCommands: [UIKeyCommand]? {
        return "wedcxzaqufhrytjnlvog".map({ (c: Character) -> UIKeyCommand in
            return UIKeyCommand(input: String(c), modifierFlags: [], action: #selector(handlerKeyInput(command:)))
        })
    }

UIResponderのbecomeFirstResponder()を使って、キー入力が自分に来るようにします。

ViewController.swift
    override func viewDidAppear(_ animated: Bool) {
        _ = self.becomeFirstResponder()
    }

UIResponder.keyCommandsをUnityで利用する。

ネイティブプラグインを作ります。

step.1 指定されたキー入力を受け取り、通知するViewControllerを実装する

KeyboarInputDetectorViewController.swift

step.2 作ったViewControllerをUnityのViewのsubViewに追加する

KeyboarInputDetector.swift
        detectorViewController = KeyboarInputDetectorViewController()
        detectorViewController.view.frame = CGRect(x: 0, y: 0, width: 0, height: 0)
        detectorViewController.view.backgroundColor = .clear
        UnityGetGLViewController().view.addSubviewdetectorViewController.view

step.3 swiftのフレームワークを呼び出すネイティブプラグインを実装する

#import <KeyboarInputDetector/KeyboarInputDetector-Swift.h>

typedef void (*OnKeyboarInputHandler) (const char* input);
extern "C" {
    KeyboarInputDetector* keyboarInputDetector_init();
    void keyboarInputDetector_startDetection(KeyboarInputDetector* detector, unsigned char* str);
    void keyboarInputDetector_stopDetection(KeyboarInputDetector* detector);
    void keyboarInputDetector_registerOnKeyboarInput(KeyboarInputDetector* detector, OnKeyboarInputHandler handler);
    void keyboarInputDetector_release(KeyboarInputDetector* detector);
}

KeyboarInputDetector* keyboarInputDetector_init() {
    KeyboarInputDetector* detector = [KeyboarInputDetector alloc];
    CFRetain((CFTypeRef)detector);
    return detector;
}

void keyboarInputDetector_startDetection(KeyboarInputDetector* detector, unsigned char* str) {
    [detector startDetectionWithUnityView: UnityGetGLViewController().view
                                     keys: @"wedcxzaqufhrytjnlvog"];
}

void keyboarInputDetector_stopDetection(KeyboarInputDetector* detector) {
    [detector stopDetection];
}

void keyboarInputDetector_registerOnKeyboarInput(KeyboarInputDetector* detector, OnKeyboarInputHandler handler) {
    [detector onKeyInputWithHandler: ^(NSString* str) {
        handler([str UTF8String]);
    }];
}

step.4 Unityから呼び出す

namespace KeyboarInputDetector
{
    public class KeyboardInputDetectorIOS : IKeyboardInputDetector
    {

        [DllImport("__Internal")]
        private static extern IntPtr keyboarInputDetector_init();

        [DllImport("__Internal")]
        private static extern void keyboarInputDetector_startDetection(IntPtr detector, string str);

        [DllImport("__Internal")]
        private static extern void keyboarInputDetector_stopDetection(IntPtr detector);

        [DllImport("__Internal")]
        private static extern void keyboarInputDetector_registerOnKeyboarInput(IntPtr detector, OnKeyboarInputHandler handler);

        [DllImport("__Internal")]
        private static extern void keyboarInputDetector_release(IntPtr detector);


        private IntPtr detector;

        public KeyboardInputDetectorIOS()
        {
            detector = keyboarInputDetector_init();
        }

        ~KeyboardInputDetectorIOS()
        {
            keyboarInputDetector_release(detector);
        }

        public void StartDetection(string str)
        {
            keyboarInputDetector_startDetection(detector, str);
            keyboarInputDetector_registerOnKeyboarInput(detector, HandlerOnKeyboardInput);
        }

        public void StopDetection()
        {
            keyboarInputDetector_stopDetection(detector);
        }

        public event OnKeyboardInputDelegate OnKeyboardInput
        {
            add { onKeyboardInput += value; }
            remove  { onKeyboardInput -= value; }
        }
        private static event OnKeyboardInputDelegate onKeyboardInput;

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate void OnKeyboarInputHandler(string input);

        [MonoPInvokeCallback(typeof(OnKeyboarInputHandler))]
        private static void HandlerOnKeyboardInput(string input)
        {
            if (onKeyboardInput != null)
                onKeyboardInput(input);
        }
    }
}
4
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
fuziki

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
4
Help us understand the problem. What is going on with this article?