catalogue
- [ground cat] games
- first ️⃣ Step 1: build scene and model configuration
- second ️⃣ Step: write a script to let the cat jump out automatically
- third ️⃣ Step: click the code to hit
- fourth ️⃣ Step, add a script that randomly lets the kitten jump out
- fifth ️⃣ Step: go to the voice network to download the SDK for audio calls, and create a project to obtain the APP ID
- sixth ️⃣ Step: connect the sound network audio SDK to the project
- summary
preface
- I just got in touch with the voice call SDK of the voice network two days ago. I think it's very interesting
- Let's bring you a little game of "hitting the ground cat" today
- Incidentally, access the sound network SDK to realize the function of a world chat channel!
[ground cat] games
This little game is actually very simple. It's still very interesting to get it done with three scripts!
Let's take a look at the renderings:
Let's talk about the production steps of this little game!
first ️⃣ Step 1: build scene and model configuration
This step is very simple. First, build a scene casually
Because it's a ground cat, we add some pits to let the kitten jump out and let us fight!
Then add a hammer on it and hit it when we click the mouse!
Then hide the kitten under the pit. Later, write a script to let him jump out and let us play
second ️⃣ Step: write a script to let the cat jump out automatically
The code is very simple. First declare several states of the cat, such as: below, above, beaten, etc
Then we write a judgment condition to let the cat do different things in different states!
The core code is as follows:
enum State{ UNDER_GROUND, UP, ON_GROUND, DOWN, HIT, } State state; void Update () { if (this.state == State.UP) { transform.Translate (0, this.moveSpeed, 0); if (transform.position.y > TOP) { transform.position = new Vector3 (transform.position.x, TOP, transform.position.z); this.state = State.ON_GROUND; this.tmpTime = 0; } } else if (this.state == State.ON_GROUND) { this.tmpTime += Time.deltaTime; if (this.tmpTime > this.waitTime) { this.state = State.DOWN; } } else if (this.state == State.DOWN) { transform.Translate (0, -this.moveSpeed, 0); if (transform.position.y < BOTTOM) { transform.position = new Vector3(transform.position.x, BOTTOM, transform.position.z); this.state = State.UNDER_GROUND; } } }
In this way, our kittens can display different effects according to different states!
third ️⃣ Step: click the code to hit
Because the effect we do is to hit the hammer wherever the mouse points So here's a script for the hammer to follow the coordinates of the mouse when he clicks!
The core code is as follows:
void Update () { if(Input.GetMouseButtonDown(0)) { Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit, 100)) { GameObject mole = hit.collider.gameObject; bool isHit = mole.GetComponent<MoleController> ().Hit (); // if hit the mole, show hummer and effect if (isHit) { StartCoroutine (Hit (mole.transform.position)); ScoreManager.score += 10; } } } }
fourth ️⃣ Step, add a script that randomly lets the kitten jump out
In the first step, we wrote that kittens will do different things according to different states
You also need to write a script to control the kitten's random jump out, so as to increase the playability of the game!
The core code is as follows:
IEnumerator Generate() { this.generate = true; while (this.generate) { // wait to generate next group yield return new WaitForSeconds (1.0f); int n = moles.Count; int maxNum = (int)this.maxMoles.Evaluate ( GameManager.time ); for (int i = 0; i < maxNum; i++) { // select mole to up this.moles [Random.Range (0, n)].Up (); yield return new WaitForSeconds (0.3f); } } }
So our little game is finished! However, the SDK of the sound network has not been added to realize the function of a world chat channel
So keep looking down!
fifth ️⃣ Step: go to the voice network to download the SDK for audio calls, and create a project to obtain the APP ID
The address of the sound network is below. If you don't know, you can get to know it briefly~
Sound network official website: https://www.agora.io/cn/community/
First, you need to register after you go in. It's very simple~
Then find the place to download the SDK: https://docs.agora.io/cn/All/downloads?platform=Unity
The sound network supports many platforms. Anyway, all the platforms I know cooperate with the sound network. I have to say that the sound network is still very powerful!
Then we find Unity's audio SDK to download
Drop in when downloading the SDK Console Create a project
Since we are used for testing, just select the debugging mode directly. You can refer to the official website document to see the difference between the two: https://docs.agora.io/cn/Agora%20Platform/token?platform=All%20Platforms
After successful creation, click the APP ID button to copy it, which will be used in the following code!
sixth ️⃣ Step: connect the sound network audio SDK to the project
In the previous step, we have completed the audio SDK, and there is also an example project
We can learn when it is convenient for us to access!
Here, we can directly put the downloaded SDK into our project
Then we create a new script to manage the world chat channel!
The core code is as follows:
using UnityEngine; using UnityEngine.UI; #if(UNITY_2018_3_OR_NEWER) using UnityEngine.Android; #endif using agora_gaming_rtc; public class HelloUnity3D : MonoBehaviour { private InputField mChannelNameInputField;//Channel number public Text mShownMessage;//Tips private Text versionText;//Version number public Button joinChannel;//Join the room public Button leaveChannel;//Leave the room private Button muteButton;//Mute private IRtcEngine mRtcEngine = null; // After entering the App ID, delete it outside the App ID## [SerializeField] private string AppID = "app_id"; void Awake() { QualitySettings.vSyncCount = 0; Application.targetFrameRate = 30; //muteButton.enabled = false; CheckAppId(); } // Initialize void Start() { #if (UNITY_2018_3_OR_NEWER) // Judge whether there is microphone permission. If there is no permission, take the initiative to apply for permission if (!Permission.HasUserAuthorizedPermission(Permission.Microphone)) { Permission.RequestUserPermission(Permission.Microphone); } #endif joinChannel.onClick.AddListener(JoinChannel); leaveChannel.onClick.AddListener(LeaveChannel); //muteButton.onClick.AddListener(MuteButtonTapped); mRtcEngine = IRtcEngine.GetEngine(AppID); //versionText.GetComponent().text = "Version : " + getSdkVersion(); //Callback after adding channel successfully mRtcEngine.OnJoinChannelSuccess += (string channelName, uint uid, int elapsed) => { string joinSuccessMessage = string.Format("Add channel callback uid: {0}, channel: {1}, version: {2}", uid, channelName, getSdkVersion()); Debug.Log(joinSuccessMessage); mShownMessage.GetComponent<Text>().text = (joinSuccessMessage); //muteButton.enabled = true; }; //Leave channel callback. mRtcEngine.OnLeaveChannel += (RtcStats stats) => { string leaveChannelMessage = string.Format("Leave channel callback time {0}, tx: {1}, rx: {2}, tx kbps: {3}, rx kbps: {4}", stats.duration, stats.txBytes, stats.rxBytes, stats.txKBitRate, stats.rxKBitRate); Debug.Log(leaveChannelMessage); mShownMessage.GetComponent<Text>().text = (leaveChannelMessage); //muteButton.enabled = false; // Reset mute key status //if (isMuted) // { // MuteButtonTapped(); //} }; //The remote user joins the callback of the current channel. mRtcEngine.OnUserJoined += (uint uid, int elapsed) => { string userJoinedMessage = string.Format("Remote user joins current channel callback uid {0} {1}", uid, elapsed); Debug.Log(userJoinedMessage); mShownMessage.GetComponent<Text>().text = (userJoinedMessage); }; //The remote user leaves the current channel for callback. mRtcEngine.OnUserOffline += (uint uid, USER_OFFLINE_REASON reason) => { string userOfflineMessage = string.Format("Remote user leaving current channel callback uid {0} {1}", uid, reason); Debug.Log(userOfflineMessage); mShownMessage.GetComponent<Text>().text = (userOfflineMessage); }; // User volume prompt callback. mRtcEngine.OnVolumeIndication += (AudioVolumeInfo[] speakers, int speakerNumber, int totalVolume) => { if (speakerNumber == 0 || speakers == null) { Debug.Log(string.Format("Local user volume prompt callback {0}", totalVolume)); } for (int idx = 0; idx < speakerNumber; idx++) { string volumeIndicationMessage = string.Format("{0} onVolumeIndication {1} {2}", speakerNumber, speakers[idx].uid, speakers[idx].volume); Debug.Log(volumeIndicationMessage); } }; //User mute prompt callback mRtcEngine.OnUserMutedAudio += (uint uid, bool muted) => { string userMutedMessage = string.Format("User mute prompt callback uid {0} {1}", uid, muted); Debug.Log(userMutedMessage); mShownMessage.GetComponent<Text>().text = (userMutedMessage); }; //Warning callback occurred mRtcEngine.OnWarning += (int warn, string msg) => { string description = IRtcEngine.GetErrorDescription(warn); string warningMessage = string.Format("Warning callback occurred {0} {1} {2}", warn, msg, description); Debug.Log(warningMessage); }; //Error callback occurred mRtcEngine.OnError += (int error, string msg) => { string description = IRtcEngine.GetErrorDescription(error); string errorMessage = string.Format("Error callback occurred {0} {1} {2}", error, msg, description); Debug.Log(errorMessage); }; // The current call statistics callback is triggered every two seconds. mRtcEngine.OnRtcStats += (RtcStats stats) => { string rtcStatsMessage = string.Format("onRtcStats callback duration {0}, tx: {1}, rx: {2}, tx kbps: {3}, rx kbps: {4}, tx(a) kbps: {5}, rx(a) kbps: {6} users {7}", stats.duration, stats.txBytes, stats.rxBytes, stats.txKBitRate, stats.rxKBitRate, stats.txAudioKBitRate, stats.rxAudioKBitRate, stats.userCount); //Debug.Log(rtcStatsMessage); int lengthOfMixingFile = mRtcEngine.GetAudioMixingDuration(); int currentTs = mRtcEngine.GetAudioMixingCurrentPosition(); string mixingMessage = string.Format("Mixing File Meta {0}, {1}", lengthOfMixingFile, currentTs); //Debug.Log(mixingMessage); }; //Voice route has changed callback. (effective only on mobile platforms) mRtcEngine.OnAudioRouteChanged += (AUDIO_ROUTE route) => { string routeMessage = string.Format("onAudioRouteChanged {0}", route); Debug.Log(routeMessage); }; //Token expiration callback mRtcEngine.OnRequestToken += () => { string requestKeyMessage = string.Format("OnRequestToken"); Debug.Log(requestKeyMessage); }; // Network interrupt callback (triggered only after successful establishment) mRtcEngine.OnConnectionInterrupted += () => { string interruptedMessage = string.Format("OnConnectionInterrupted"); Debug.Log(interruptedMessage); }; // Network connection loss callback mRtcEngine.OnConnectionLost += () => { string lostMessage = string.Format("OnConnectionLost"); Debug.Log(lostMessage); }; // Set Log level mRtcEngine.SetLogFilter(LOG_FILTER.INFO); // 1. Set it to free speech mode, which is often used for one-to-one or group chat mRtcEngine.SetChannelProfile(CHANNEL_PROFILE.CHANNEL_PROFILE_COMMUNICATION); //2. Set to live mode, which is suitable for chat rooms or interactive video streaming. //mRtcEngine.SetChannelProfile (CHANNEL_PROFILE.CHANNEL_PROFILE_LIVE_BROADCASTING); //3. Set to game mode. This profile uses a lower bit rate codec and consumes less power. It is applicable to game scenes where all game players can talk freely. //mRtcEngine.SetChannelProfile(CHANNEL_PROFILE.CHANNEL_PROFILE_GAME); //Set user roles in the live broadcast scenario. //mRtcEngine.SetClientRole (CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER); } private void CheckAppId() { Debug.Assert(AppID.Length > 10, "First, please Game Controller Fill in your name on the object AppId. ."); GameObject go = GameObject.Find("AppIDText"); if (go != null) { Text appIDText = go.GetComponent<Text>(); if (appIDText != null) { if (string.IsNullOrEmpty(AppID)) { appIDText.text = "AppID: " + "UNDEFINED!"; appIDText.color = Color.red; } else { appIDText.text = "AppID: " + AppID.Substring(0, 4) + "********" + AppID.Substring(AppID.Length - 4, 4); } } } } /// ///Join channel /// public void JoinChannel() { // Obtain the channel name from the input box of the interface string channelName = "adc666"; // Obtain the channel name from the input box of the interface //string channelNameOld = mChannelNameInputField.text.Trim(); Debug.Log(string.Format("Obtain the channel name from the input box of the interface {0}", channelName)); if (string.IsNullOrEmpty(channelName)) { return; } // Join channel // channelKey: dynamic secret key. We didn't select the Token mode at first, so null can be passed in here; Otherwise, the Token generated by the server needs to be passed in // channelName: channel name // info: the developer's attached information (not necessary) will not be transmitted to other users in the channel // uid: user ID, 0 is automatically assigned mRtcEngine.JoinChannelByKey(channelKey: null, channelName: channelName, info: "extra", uid: 0); //Join channels and set publish and subscribe status. //mRtcEngine.JoinChannel(channelName, "extra", 0); } /// ///Leave channel /// public void LeaveChannel() { // Leave channel mRtcEngine.LeaveChannel(); string channelName = "abc666"; Debug.Log(string.Format("left channel name {0}", channelName)); } void OnApplicationQuit() { if (mRtcEngine != null) { // Destroy IRtcEngine IRtcEngine.Destroy(); } } /// ///Query SDK version number. /// /// public string getSdkVersion() { string ver = IRtcEngine.GetSdkVersion(); return ver; } bool isMuted = false; void MuteButtonTapped() { //Set mute or unmute string labeltext = isMuted ? "Mute" : "Unmute"; Text label = muteButton.GetComponentInChildren<Text>(); if (label != null) { label.text = labeltext; } isMuted = !isMuted; // Set mute (stop pushing local audio) mRtcEngine.EnableLocalAudio(!isMuted); Debug.Log("Mute method execution completed"); } }
Here I have set the default channel, which means that everyone enters one channel to chat when they click
But this is not good! It's convenient here. That's it~
Here we are done. We have realized the function of adding the world chat channel to this little game of hitting the ground cat!
Although the function may not be perfect, you'll be familiar with it after using it a few more times. Hey, hey!
summary
- In this paper, I made a simple ground cat game and accessed the audio SDK of the sound network
- There are still many areas that need to be improved for the small projects that they have worked overtime
- This article briefly introduces it, which is still very interesting ha ha! I'll see you next time!