
Good day to all.
Let's start with what Unity 3d is. In short, this is a three-dimensional game engine. The official site is available free version, pro version and version with the ability to upload applications to mobile platforms are already worth the money.
This engine has rich features, but it doesn’t know how to do anything, and you still have to do some things natively. For example, you had the task of displaying a web page (for example, your personal page when clicking on a link from the main menu of the game). The WWW class is designed to work with the network in unity, but it only has the ability to exchange data with web pages; it cannot cope with the task of rendering. You go through all the options and decide that it is better to display the web page using native iOS WebView (I’ll just say that the article is not about how to write a Web View on Objective-C, but rather how to make friends with Unity). First you need to open xCode (or AppCode) and create an empty application (here it should be noted that the project created by Unity does not support ARC; therefore, you will have to clear the memory with pens). We will need two Objective-C classes. Let's call them WebController and WebViewCaller. Accordingly, four WebController.h, WebController.m, WebViewCaller.h, and WebViewCaller.m files will be created. Files with the .h extension are header files, all class methods should be described there, .m files are their direct implementation. To begin with, we will decide what we want from our web view. We want the class to accept two NSString parameters, the first is the page to which we must go if there is a connection to the network, and the second is the path in the file system to the html page that we want to load by default if there is no connection to the Internet. For the WebController, I will provide only the .h file, we will focus on WebViewCaller in more detail.
')
So, with the help of habr, google and stackoverflow, we wrote a class that creates a web view. The .h file looks like this to us:
@interface WebController : UIViewController <UIWebViewDelegate> - (id)initWithOnlineHtml:(NSString*) _onlineHtml withOfflineHtml:(NSString*) _offlineHtml; @end
This is actually the public signature of the constructor with the name initWithOnlineHtml: withOfflineHtml: and two string parameters _onlineHtml and _offlineHtml, the purpose of which I think should be clear to everyone.
Next we need to add this twist to our application. We will do this in our WebVievCaller class. He should draw our web view, and draw a button back, which will return us to our game. For starters, our class will look like this (.h file)
#import <Foundation/Foundation.h> #import "TEWebController.h" @interface WebViewCaller : NSObject -(IBAction)quitBack:(id)sender; -(void) callViewWithOnlineHtml:(NSString*) _onlineHtml withOfflineHtml:(NSString*) _offlineHtml; @end
quitBack is a function that will be called by pressing a button, callViewWithOnlineHtml: withOfflineHtml: will actually add our WebView to the current window and draw a button. So our class looks like this:
@implementation WebViewCaller UIWindow* window; -(IBAction)quitBack:(id)sender { NSLog(@"%d",clicked.tag); } -(void) callViewWithOnlineHtml:(NSString*) _onlineHtml withOfflineHtml:(NSString*) _offlineHtml { TEWebController* webController = [[TEWebController alloc] initWithOnlineHtml:_onlineHtml withOfflineHtml:_offlineHtml]; window = [[UIApplication sharedApplication] keyWindow];
Here you can stay a little more. We create our web view with the parameters that came from unity, line 1 we get the current window, line 2 we set our web view as a display controller, from line 3 to line 4 we create a button that so far just displays its tag in the console and, finally line 4 we add our button to the screen.
Next comes the reason for which this article was conceived. We need to add all this joy in unity and make a button back.
First we need to add our classes to the folder "/ pathToYourProject / Assets / Plugins / iOS /" (no further attachments are allowed). Why did we do that, you probably ask. Unity creates an xCode project when building it, and xCode picks up the files in this folder and adds it to its project. In the xCode project, they are in the Libraries folder. To connect a plugin, functions must be declared in the “C” syntax. That is, we must declare our function as
void _CalliOSWebView(const char *onlineHtml, const char *offlineHtml);
(the string type in "C #" "matches const char * in" C ", so we still need to cast our const char * variables in NSString and call callViewWithOnlineHtml: withOfflineHtml: with the given parameters). For this, outside the class after we write the function to The "C" style converts the input parameters into an NSString and causes callViewWithOnlineHtml: withOfflineHtml :.
If you try to connect the Objective-C method, you will get an error like this:
Undefined symbols for architecture armv7: "__CalliOSWebView", referenced from: RegisterMonoModules() in RegisterMonoModules.o ld: symbol(s) not found for architecture armv7 clang: error: linker command failed with exit code 1 (use -v to see invocation)
We make the necessary changes to our class. Now our .m file should look like this:
@implementation WebViewCaller UIWindow* window; -(IBAction)quitBack:(id)sender { NSLog(@"%d",clicked.tag); } -(void) callViewWithOnlineHtml:(NSString*) _onlineHtml withOfflineHtml:(NSString*) _offlineHtml { TEWebController* webController = [[TEWebController alloc] initWithOnlineHtml:_onlineHtml withOfflineHtml:_offlineHtml]; window = [[UIApplication sharedApplication] keyWindow];
You also need to add a description of our function in the .h file
#import <Foundation/Foundation.h> #import "WebController.h" @interface WebViewCaller : NSObject -(IBAction)quitBack:(id)sender; -(void) callViewWithOnlineHtml:(NSString*) _onlineHtml withOfflineHtml:(NSString*) _offlineHtml; @end #ifdef __cplusplus extern "C" { #endif void _CalliOSWebView(const char *onlineHtml, const char *offlineHtml); #ifdef __cplusplus } #endif
Now we can use our plugin. Unity uses [DllImport (“PluginName”)] for this, but since we are working with iOS where the plugins are statically included in the assembly, we will use [DllImport ("__Internal")].
The code in unity will look like this:
public static void CallForWebPage() { if (Application.platform == RuntimePlatform.IPhonePlayer) { _CalliOSWebView("http://habrahabr.ru", Application.dataPath + "/Raw/test.html"); } }
I think everything should be clear here, except perhaps the second argument in the _CalliOSWebView call. It refers to the file saved in the iOS device's file system. But how do we put it there? To do this, there is StreamingAssets in unity (files placed in this folder will remain unchanged after building the project). Create this folder and put our test.html there. Now, to display the web view, it will be necessary to call CallForWebPage () from the unit, but the question will remain with the back button. It can be solved as follows. We save the view of the unit, we enclose our web view, by pressing the button we restore the view of the unit. The only problem is that the unit does not know about it, and the game, the sounds continue. But this is easily solved when desired. The implementation of the button is presented below:
@implementation WebViewCaller UIViewController *unityViewController; UIWindow* window; -(IBAction)quitBack:(id)sender { [window setRootViewController:unityViewController]; } -(void) callViewWithOnlineHtml:(NSString*) _onlineHtml withOfflineHtml:(NSString*) _offlineHtml { WebController* webController = [[TEWebController alloc] initWithOnlineHtml:_onlineHtml withOfflineHtml:_offlineHtml]; window = [[UIApplication sharedApplication] keyWindow]; unityViewController = [UIApplication sharedApplication].keyWindow.rootViewController; [window setRootViewController:webController]; UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [button addTarget:self action:@selector(quitBack:) forControlEvents:UIControlEventTouchUpInside]; [button setTitle:@"<<" forState:UIControlStateNormal]; button.frame = CGRectMake(0, 0, 160.0, 40.0); [window addSubview:button]; [webController release]; } @end void _CalliOSWebView(const char *onlineHtml, const char *offlineHtml) { NSString *onlineHtmlString = [[NSString alloc] initWithUTF8String:onlineHtml]; NSString *offlineHtmlString = [[NSString alloc] initWithUTF8String:offlineHtml]; WebViewCaller *caller = [[WebViewCaller alloc] init]; [caller callViewWithOnlineHtml:onlineHtmlString withOfflineHtml:offlineHtmlString]; [onlineHtmlString release]; [offlineHtmlString release]; }
The only question left is how to debug this. I decided it for myself as follows. Go to the folder where we collected the iOS project. We open it from xCode, edit it, make debugging and do everything we want (remember, our plugins are in the Libraries folder). Then copy-paste the changes to our classes in the folder "/ pathToYourProject / Assets / Plugins / iOS /".
That's all. If the WebController class is written correctly, then everything will start and work. I haven’t done programming with Objective-C before, and some things may seem clumsy and crooked to professionals, for which I apologize, but I hope that I could convey the basic idea of ​​how to connect plug-ins, and I hope that I could save at least some hours of work. Thanks for attention.
Who is interested in Unity can advise the following resources:
unity3d.com - official site;
answers.unity3d.com - questions and answers. The most, in my opinion, useful resource;
forum.unity3d.com - forum about unit;
docs.unity3d.com - official documentation.