TestHelloUnityVideo.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. using agora_gaming_rtc;
  4. using agora_utilities;
  5. // this is an example of using Agora Unity SDK
  6. // It demonstrates:
  7. // How to enable video
  8. // How to join/leave channel
  9. //
  10. public class TestHelloUnityVideo
  11. {
  12. // instance of agora engine
  13. private IRtcEngine mRtcEngine;
  14. private Text MessageText;
  15. // a token is a channel key that works with a AppID that requires it.
  16. // Generate one by your token server or get a temporary token from the developer console
  17. private string token = "";
  18. // load agora engine
  19. public void loadEngine(string appId)
  20. {
  21. // start sdk
  22. Debug.Log("initializeEngine");
  23. if (mRtcEngine != null)
  24. {
  25. Debug.Log("Engine exists. Please unload it first!");
  26. return;
  27. }
  28. // init engine
  29. mRtcEngine = IRtcEngine.GetEngine(appId);
  30. // enable log
  31. mRtcEngine.SetLogFilter(LOG_FILTER.DEBUG | LOG_FILTER.INFO | LOG_FILTER.WARNING | LOG_FILTER.ERROR | LOG_FILTER.CRITICAL);
  32. }
  33. public void join(string channel)
  34. {
  35. Debug.Log("calling join (channel = " + channel + ")");
  36. if (mRtcEngine == null)
  37. return;
  38. // set callbacks (optional)
  39. mRtcEngine.OnJoinChannelSuccess = onJoinChannelSuccess;
  40. mRtcEngine.OnUserJoined = onUserJoined;
  41. mRtcEngine.OnUserOffline = onUserOffline;
  42. mRtcEngine.OnWarning = (int warn, string msg) =>
  43. {
  44. Debug.LogWarningFormat("Warning code:{0} msg:{1}", warn, IRtcEngine.GetErrorDescription(warn));
  45. };
  46. mRtcEngine.OnError = HandleError;
  47. // enable video
  48. mRtcEngine.EnableVideo();
  49. // allow camera output callback
  50. mRtcEngine.EnableVideoObserver();
  51. // join channel
  52. /* This API Assumes the use of a test-mode AppID
  53. mRtcEngine.JoinChannel(channel, null, 0);
  54. */
  55. /* This API Accepts AppID with token; by default omiting info and use 0 as the local user id */
  56. mRtcEngine.JoinChannelByKey(channelKey: token, channelName: channel);
  57. }
  58. public string getSdkVersion()
  59. {
  60. string ver = IRtcEngine.GetSdkVersion();
  61. return ver;
  62. }
  63. public void leave()
  64. {
  65. Debug.Log("calling leave");
  66. if (mRtcEngine == null)
  67. return;
  68. // leave channel
  69. mRtcEngine.LeaveChannel();
  70. // deregister video frame observers in native-c code
  71. mRtcEngine.DisableVideoObserver();
  72. }
  73. // unload agora engine
  74. public void unloadEngine()
  75. {
  76. Debug.Log("calling unloadEngine");
  77. // delete
  78. if (mRtcEngine != null)
  79. {
  80. IRtcEngine.Destroy(); // Place this call in ApplicationQuit
  81. mRtcEngine = null;
  82. }
  83. }
  84. public void EnableVideo(bool pauseVideo)
  85. {
  86. if (mRtcEngine != null)
  87. {
  88. if (!pauseVideo)
  89. {
  90. mRtcEngine.EnableVideo();
  91. }
  92. else
  93. {
  94. mRtcEngine.DisableVideo();
  95. }
  96. }
  97. }
  98. // accessing GameObject in Scnene1
  99. // set video transform delegate for statically created GameObject
  100. public void onSceneHelloVideoLoaded()
  101. {
  102. // Attach the SDK Script VideoSurface for video rendering
  103. GameObject quad = GameObject.Find("Quad");
  104. if (ReferenceEquals(quad, null))
  105. {
  106. Debug.Log("failed to find Quad");
  107. return;
  108. }
  109. else
  110. {
  111. quad.AddComponent<VideoSurface>();
  112. }
  113. GameObject cube = GameObject.Find("Cube");
  114. if (ReferenceEquals(cube, null))
  115. {
  116. Debug.Log("failed to find Cube");
  117. return;
  118. }
  119. else
  120. {
  121. cube.AddComponent<VideoSurface>();
  122. }
  123. GameObject text = GameObject.Find("MessageText");
  124. if (!ReferenceEquals(text, null))
  125. {
  126. MessageText = text.GetComponent<Text>();
  127. }
  128. GameObject bobj = GameObject.Find("HelpButton");
  129. if (bobj != null)
  130. {
  131. Button button = bobj.GetComponent<Button>();
  132. if (button!=null)
  133. {
  134. button.onClick.AddListener(HandleHelp);
  135. }
  136. }
  137. }
  138. void HandleHelp()
  139. {
  140. #if UNITY_2020_3_OR_NEWER && PLATFORM_STANDALONE_OSX
  141. // this very easy to forget for MacOS
  142. HandleError(-2, "if you don't see any video, did you set the MacOS plugin bundle to AnyCPU?");
  143. #else
  144. HandleError(-1, "if you don't see any video, please check README for help");
  145. #endif
  146. }
  147. // implement engine callbacks
  148. private void onJoinChannelSuccess(string channelName, uint uid, int elapsed)
  149. {
  150. Debug.Log("JoinChannelSuccessHandler: uid = " + uid);
  151. GameObject textVersionGameObject = GameObject.Find("VersionText");
  152. textVersionGameObject.GetComponent<Text>().text = "SDK Version : " + getSdkVersion();
  153. }
  154. // When a remote user joined, this delegate will be called. Typically
  155. // create a GameObject to render video on it
  156. private void onUserJoined(uint uid, int elapsed)
  157. {
  158. Debug.Log("onUserJoined: uid = " + uid + " elapsed = " + elapsed);
  159. // this is called in main thread
  160. // find a game object to render video stream from 'uid'
  161. GameObject go = GameObject.Find(uid.ToString());
  162. if (!ReferenceEquals(go, null))
  163. {
  164. return; // reuse
  165. }
  166. // create a GameObject and assign to this new user
  167. VideoSurface videoSurface = makeImageSurface(uid.ToString());
  168. if (!ReferenceEquals(videoSurface, null))
  169. {
  170. // configure videoSurface
  171. videoSurface.SetForUser(uid);
  172. videoSurface.SetEnable(true);
  173. videoSurface.SetVideoSurfaceType(AgoraVideoSurfaceType.RawImage);
  174. }
  175. }
  176. public VideoSurface makePlaneSurface(string goName)
  177. {
  178. GameObject go = GameObject.CreatePrimitive(PrimitiveType.Plane);
  179. if (go == null)
  180. {
  181. return null;
  182. }
  183. go.name = goName;
  184. // set up transform
  185. go.transform.Rotate(-90.0f, 0.0f, 0.0f);
  186. float yPos = Random.Range(3.0f, 5.0f);
  187. float xPos = Random.Range(-2.0f, 2.0f);
  188. go.transform.position = new Vector3(xPos, yPos, 0f);
  189. go.transform.localScale = new Vector3(0.25f, 0.5f, .5f);
  190. // configure videoSurface
  191. VideoSurface videoSurface = go.AddComponent<VideoSurface>();
  192. return videoSurface;
  193. }
  194. private const float Offset = 100;
  195. public VideoSurface makeImageSurface(string goName)
  196. {
  197. GameObject go = new GameObject();
  198. if (go == null)
  199. {
  200. return null;
  201. }
  202. go.name = goName;
  203. // to be renderered onto
  204. go.AddComponent<RawImage>();
  205. // make the object draggable
  206. go.AddComponent<UIElementDragger>();
  207. GameObject canvas = GameObject.Find("Canvas");
  208. if (canvas != null)
  209. {
  210. go.transform.parent = canvas.transform;
  211. }
  212. // set up transform
  213. go.transform.Rotate(0f, 0.0f, 180.0f);
  214. float xPos = Random.Range(Offset - Screen.width / 2f, Screen.width / 2f - Offset);
  215. float yPos = Random.Range(Offset, Screen.height / 2f - Offset);
  216. go.transform.localPosition = new Vector3(xPos, yPos, 0f);
  217. go.transform.localScale = new Vector3(3f, 4f, 1f);
  218. // configure videoSurface
  219. VideoSurface videoSurface = go.AddComponent<VideoSurface>();
  220. return videoSurface;
  221. }
  222. // When remote user is offline, this delegate will be called. Typically
  223. // delete the GameObject for this user
  224. private void onUserOffline(uint uid, USER_OFFLINE_REASON reason)
  225. {
  226. // remove video stream
  227. Debug.Log("onUserOffline: uid = " + uid + " reason = " + reason);
  228. // this is called in main thread
  229. GameObject go = GameObject.Find(uid.ToString());
  230. if (!ReferenceEquals(go, null))
  231. {
  232. Object.Destroy(go);
  233. }
  234. }
  235. #region Error Handling
  236. private int LastError { get; set; }
  237. private void HandleError(int error, string msg)
  238. {
  239. if (error == LastError)
  240. {
  241. return;
  242. }
  243. if (string.IsNullOrEmpty(msg))
  244. {
  245. msg = string.Format("Error code:{0} msg:{1}", error, IRtcEngine.GetErrorDescription(error));
  246. }
  247. switch (error)
  248. {
  249. case 101:
  250. msg += "\nPlease make sure your AppId is valid and it does not require a certificate for this demo.";
  251. break;
  252. }
  253. Debug.LogError(msg);
  254. if (MessageText != null)
  255. {
  256. if (MessageText.text.Length > 0)
  257. {
  258. msg = "\n" + msg;
  259. }
  260. MessageText.text += msg;
  261. }
  262. LastError = error;
  263. }
  264. #endregion
  265. }