ARC Semantic issue/ARC Restrictions - iOS
Hello,
After days testing with Android and iOS platforms I've been triggered today by this error while compiling in XCode 9 (after doing the last change of this post):
It's weird because with Android it works perfectly after building in Unity. I'm going to share the XCode project with you, if you want to try it:
Do you guys have any idea of what's causing that? I'm googled it, but I was not able to identify.
Best.
first. CustomVideoPlayer class has not "_play" function.
second. CustomVideoPlayer, VideoPlayerPlugin class must be diable Auto Reference Count. you must set plugin "-fno-objc-arc" at Build Phase->Compile Sources-> CustomVideoPlayer.mm, VideoPlayerPlugin.mm
third. check fuction "observeValueForKeyPath" in CustomVideoPlayer.mm. AVPlayerStatus can get at player.status variable.
end. I think your plugin named "VideoPlayerPlugin.mm" is not linked Unity. , some functions. like
"_VideoPlayerPluginGetAudioTrack", referenced from:
"_VideoPlayerPluginGetCurrentSeekPercent", referenced from:
check your c# file.
Sorry man, I'm kind of lost here.
1. how can I add a "_play" function then?
2. I'm not sure if I get it, but I'll looking into it.
3. Don't get it too, but I'll check. And if I found that, what can I do?
4. And how can I solve that?
Sorry guys, that's a very hard to me to understand it.
By the way, you can understand what I'm trying to do here by this post and possibly how this error could happens.
Best.
i think your plugin for video texture is broken.(You need to clean up code for video.)
clear up c# code or code in Plugin folder.
Add unitypackage(Youtube Video Player?) for video texture again.
Ok. I did the clean up and tested the plugins individually. Happens that plugin EasyMovieTexture (has iOS compatibility) was causing all errors and it has been yet in my unity project folder for no reason at this moment, since I replaced it with Youtube Video Player plugin.
So, I removed EasyMovieTexture and tested yours plugin with Youtube player plugin. Worked fine in iOS! But, the video was playing from the moment that app starts. We want the video to start playing when target is found and pause when target is lost. Then I used the same codes changes from previously post, that has been worked with Android, in ImageTrackableBehaviour.cs and SimplePlayback.cs (script from Youtube player's plugin) which is described below:
In SimplePlayback.cs I added this variables:
//IMG TRCK BHVR PLAY
public void StartPlaying()
{
unityVideoPlayer.Play();
}
//IMG TRCK BHVR PAUSE
public void StopPlaying()
{
unityVideoPlayer.Pause();
}
And in ImageTrackableBehaviour.cs I called those variables:
public class ImageTrackableBehaviour : AbstractImageTrackableBehaviour
{
public override void OnTrackSuccess(string id, string name, Matrix4x4 poseMatrix)
{
Renderer[] rendererComponents = GetComponentsInChildren<Renderer>(true);
Collider[] colliderComponents = GetComponentsInChildren<Collider>(true);
SimplePlayback[] videoplayers = GetComponentsInChildren<SimplePlayback>(true);
SimplePlayback[] StartPlaying = GetComponentsInChildren<SimplePlayback>(true);
// Enable renderers
foreach (Renderer component in rendererComponents)
{
component.enabled = true;
}
// Enable colliders
foreach (Collider component in colliderComponents)
{
component.enabled = true;
}
// Enable video player attached
foreach (SimplePlayback videoplayer in videoplayers)
{
videoplayer.enabled = true;
}
// Start Playing
foreach (SimplePlayback unityVideoPlayer in StartPlaying)
{
unityVideoPlayer.StartPlaying();
}
transform.position = MatrixUtils.PositionFromMatrix(poseMatrix);
transform.rotation = MatrixUtils.QuaternionFromMatrix(poseMatrix);
}
public override void OnTrackFail()
{
Renderer[] rendererComponents = GetComponentsInChildren<Renderer>(true);
Collider[] colliderComponents = GetComponentsInChildren<Collider>(true);
SimplePlayback[] videoplayers = GetComponentsInChildren<SimplePlayback>(true);
SimplePlayback[] StopPlaying = GetComponentsInChildren<SimplePlayback>(true);
// Disable renderer
foreach (Renderer component in rendererComponents)
{
component.enabled = false;
}
// Disable collider
foreach (Collider component in colliderComponents)
{
component.enabled = false;
}
// Disable video player attached
foreach (SimplePlayback videoplayer in videoplayers)
{
videoplayer.enabled = false;
}
// Stop Playing
foreach (SimplePlayback unityVideoPlayer in StopPlaying)
{
unityVideoPlayer.StopPlaying();
}
It should work fine, right? But it didn't. The video freeze in the first frame and the audio chokes and don't reproduce too. Also happens an fps drop, if target is lost fps goes to 30, if is found fps goes to 9/10.
Do you guys have any idea how to solve that with iOS? By the way, here follows the package file so you could test it too: SimpleTest (scene called Simple).
Best.
Any thoughts on this?
Sample Project Download this.
deletet this script.
foreach (SimplePlayback videoplayer in videoplayers)
{
videoplayer.enabled = true;
}
/ Start Playing
foreach (SimplePlayback unityVideoPlayer in StartPlaying)
{
unityVideoPlayer.StartPlaying();
}
See my sample project scene named 'test'. you can see Quad in ImageTrackable.
i made 'SimpleVideoController' script for you. Video must be control in Update function.
Awesome!
Your scene worked well in Android and iOS, the only problem was audio that didn't shows up in any platform, even PC. We need audio too. Any ideas of how we can get it to work?
UPDATE
I just added the audio component and linked with the player. Worked very well in all platforms.
Now, we reached our main objective here! Thank you ALL guys for the incredible support.
Best.
1. Set VideoPlayer -> URL
2. Audio Output Mode -> Audio Source
3. Add Component "Audio Source"
4. Put Audio Source upper "3" at VideoPlayer->Audio Output Mode->Controlled Tracks(set 1)->Track 0-> Audio Source
Hi,
Any ideas on how can I get the videos to download just when the target is found?
I've tried to put the (StartCoroutine(resolver.GetDownloadUrls(FinishLoadingUrls, videoId, false));) from your previous script "SimpleVideoController" inside "trackingResult.GetCount" in void Update to start when the target is found, but it doesn't work. Since does not work, then, I put it into a button to call the Coroutine, happens that if I've more than one target all buttons shows at the same time.
Any ideas?
Best.
Any thoughts on this?
Canvas UI does not controll by TARGET GameObject. then you must be controll Quad(SimpleVideoController). use "videoRender.enabled". because you call function "DisableAllTrackables()" in ImageTrackerSample/Update(). that function call trackable.Value.OnTrackFail() and you can find function 'OnTrackSuccess()' is just controll Renderer component, Collider component.
so. you must be make function which controll Canvas GameObject.
ex )
if (videoRender.enabled)
{
....
canvas.enbale = true;
}
else
{
canvas.enable = false;
}
Now works very nicely!
Thank you so much man! :D
Best.
Hi again,
Do you have any idea of how can I get the video to work on fullscreen mode instead in quad? In this case, the target image will going to be useful just to trigger the button to start download and play the video in fullscreen without pausing if the tracker is lost.
I've tried this approach: I've created an empty gameobject and applied this script (which is the same as you did before with a few modifications) without the MeshRenderer in it and with just the VideoPlayer component (render mode to Camera Far Plane) as the image below.
Also, the only solution I got was to change the ImageTrackableBehaviour like this to identify the state of target found/lost since the videoRender was not able to get the video in fullscreen.
This way is working out, but the video is taking a quite longer to load in comparison to yours script. I think that's something about if (!videoPlayer.isPrepared) in Update function from yours script that I could not figure out how to put it on the script that I've changed.
I'm not sure if I made myself understandable, but you have any tip or trick to improve it?
Best.
Any thoughts/tips/tricks/code/idea on this?
see this documnet https://docs.unity3d.com/ScriptReference/Handheld.PlayFullScreenMovie.html
i think when it is tracking result > 0.
use Handheld.PlayFullScreenMovie.
Interesting! I'm going to try.
Thanks.
Hi,
I've tried your approach (tracking result >0), but video was blinking before track found and after that fullscreen interface didn't play video properly. So, I've tried this approach in Update:
if (videoRender.enabled)
{
if (!videoPlayer.isPrepared)
{
gameObject.transform.localScale = Vector3.zero;
}
else
{
gameObject.transform.localScale = initializedScale;
if (videoPlayer.isPlaying)
{
Handheld.PlayFullScreenMovie(videoUrl, Color.black, FullScreenMovieControlMode.CancelOnInput);
gameObject.transform.localScale = Vector3.zero;
}
}
videoPlayer.Play();
}
But fullscreen video still doesn't play properly, which is video gets some crazy action with play function.
Can you please help me with that if you have some time?
Best.
if you want to play 'FullScreenMode', you don't use videoPlayer.
just use Handheld.PlayFullScreenMovie.
Tracking Success -> get video url -> invoke one time Handheld.PlayFullScreenMovie.
i think that crazy action is call repeate Handheld.PlayFullScreenMovie. just call once that function.
Your logic is correct, although the application by tracking result -> 1 didn't work properly (screen still blinking even if outside Update and in another void). Otherwise, the application by tracking success -> get video url -> invoke one time after Prepare video worked very well.
Thanks man!
Best.