com.adrenak.univoice 4.2.0 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -5
- package/Runtime/ClientSession.cs +23 -1
- package/Runtime/Impl/Inputs/EmptyAudioInput.cs +22 -0
- package/Runtime/Impl/Inputs/EmptyAudioInput.cs.meta +11 -0
- package/Samples~/Basic Setup Scripts/UniVoiceMirrorSetupSample.cs +199 -0
- package/Samples~/Basic Setup Scripts/UniVoiceMirrorSetupSample.cs.meta +11 -0
- package/Samples~/Basic Setup Scripts/UniVoiceMirrorSetupSample.unity +435 -0
- package/Samples~/Basic Setup Scripts/UniVoiceMirrorSetupSample.unity.meta +7 -0
- package/Samples~/Basic Setup Scripts.meta +8 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Some features of UniVoice:
|
|
|
10
10
|
* 🌐 __Configurable Network__:
|
|
11
11
|
- UniVoice is networking agnostic. Implement the `IAudioClient` and `IAudioServer` interfaces using the networking plugin of your choice to have it send audio data over any networking solution.
|
|
12
12
|
- Built-in support for:
|
|
13
|
-
- Mirror networking.
|
|
13
|
+
- Mirror networking. Note that only Client and Server modes are currently supported. Host mode is not.
|
|
14
14
|
|
|
15
15
|
* 🎤 __Configurable Audio Input__:
|
|
16
16
|
- UniVoice is audio input agnostic. You can change the source of outgoing audio by implementing the `IAudioInput` interface.
|
|
@@ -50,13 +50,22 @@ Ensure you have the NPM registry in the `manifest.json` file of your Unity proje
|
|
|
50
50
|
```
|
|
51
51
|
Then add `com.adrenak.univoice:x.y.z` to the `dependencies` in your `manifest.json` file (where x.y.z is the version you wish to install). The list of versions is available on [the UniVoice NPM page](https://www.npmjs.com/package/com.adrenak.univoice?activeTab=versions).
|
|
52
52
|
|
|
53
|
-
##
|
|
54
|
-
API reference is available here: http://www.vatsalambastha.com/univoice
|
|
53
|
+
## Useful links
|
|
54
|
+
* API reference is available here: http://www.vatsalambastha.com/univoice
|
|
55
|
+
* UniVoice blog: https://blog.vatsalambastha.com/search/label/univoice
|
|
56
|
+
* Discord server: https://discord.gg/Un6Y2sQqqe
|
|
57
|
+
|
|
58
|
+
## Integration
|
|
59
|
+
UniVoice isn't currently very drag-and-drop/low-code. The best way to integrate is to have some code perform a one time setup when your app starts and provides access to relevant objects that you can use throughout the rest of the apps runtime.
|
|
60
|
+
|
|
61
|
+
An example of this is the `UniVoiceMirrorSetupSample.cs` file that gives you access to an AudioServer that you can use in your server code and a ClientSession that you can use in your client code. For more see the "Samples" section below.
|
|
55
62
|
|
|
56
63
|
## Samples
|
|
57
|
-
This repository contains
|
|
64
|
+
This repository contains two samples:
|
|
65
|
+
* `UniVoiceMirrorSetupSample.cs` is a drag and drop component, a simple integration sample script. You can add it to your Mirror NetworkManager to get voice chat to work. No code required, it's as simple as that! It'll work as long as you have setup your project properly. For more instructions see the top of the `UniVoiceMirrorSetupSample.cs` file.
|
|
66
|
+
* A sample scene that shows the other clients in a UI as well as allows you to mute yourself/them. This sample is also Mirror based.
|
|
58
67
|
|
|
59
|
-
>
|
|
68
|
+
> UniVoice currently only supports Mirror out of the box. All the samples rely on Mirror networking to work. Follow the instructions in the "Activating non-packaged dependencies" section below for enabling Mirror in your project before trying it out. Also note that the Host mode is not supported, your server should be in Server mode only.
|
|
60
69
|
|
|
61
70
|
## Dependencies
|
|
62
71
|
[com.adrenak.brw](https://www.github.com/adrenak/brw) for reading and writing messages for communication. See `MirrorServer.cs` and `MirrorClient.cs` where they're used.
|
package/Runtime/ClientSession.cs
CHANGED
|
@@ -16,6 +16,22 @@ namespace Adrenak.UniVoice {
|
|
|
16
16
|
/// </summary>
|
|
17
17
|
public Dictionary<T, IAudioOutput> PeerOutputs { get; private set; } = new Dictionary<T, IAudioOutput>();
|
|
18
18
|
|
|
19
|
+
/// <summary>
|
|
20
|
+
/// Whether input audio will be processed. If set to false, any input audio captured by
|
|
21
|
+
/// <see cref="Input"/> would be ignored and would neither be processed by the <see cref="InputFilters"/> nor send via the <see cref="Client"/>
|
|
22
|
+
/// This can be used to create "Push to talk" style features without having to use <see cref="IAudioClient{T}.YourVoiceSettings"/>
|
|
23
|
+
/// </summary>
|
|
24
|
+
public bool InputEnabled { get; set; } = true;
|
|
25
|
+
|
|
26
|
+
/// <summary>
|
|
27
|
+
/// Whether any incoming audio from peers would be processed. If set to false, all incoming peer audio is ignored, and would
|
|
28
|
+
/// neither be processed by the <see cref="OutputFilters"/> nor outputted to the <see cref="IAudioOutput"/> of any peer.
|
|
29
|
+
/// This can be used to easily mute all the peers on the network.
|
|
30
|
+
/// Note that this doesn't stop the audio data from arriving and would consume bandwidth. Do stop reception completely
|
|
31
|
+
/// use <see cref="IAudioClient{T}.YourVoiceSettings"/>
|
|
32
|
+
/// </summary>
|
|
33
|
+
public bool OutputsEnabled { get; set; } = true;
|
|
34
|
+
|
|
19
35
|
/// <summary>
|
|
20
36
|
/// The input <see cref="IAudioFilter"/> that will be applied to the outgoing audio for all the peers.
|
|
21
37
|
/// Note that filters are executed in the order they are present in this list
|
|
@@ -69,7 +85,10 @@ namespace Adrenak.UniVoice {
|
|
|
69
85
|
PeerOutputs.Remove(id);
|
|
70
86
|
};
|
|
71
87
|
|
|
72
|
-
|
|
88
|
+
Client.OnReceivedPeerAudioFrame += (id, audioFrame) => {
|
|
89
|
+
if (!OutputsEnabled)
|
|
90
|
+
return;
|
|
91
|
+
|
|
73
92
|
if (!PeerOutputs.ContainsKey(id))
|
|
74
93
|
return;
|
|
75
94
|
|
|
@@ -94,6 +113,9 @@ namespace Adrenak.UniVoice {
|
|
|
94
113
|
input.Dispose();
|
|
95
114
|
input = value;
|
|
96
115
|
input.OnFrameReady += frame => {
|
|
116
|
+
if (!InputEnabled)
|
|
117
|
+
return;
|
|
118
|
+
|
|
97
119
|
if (InputFilters != null) {
|
|
98
120
|
foreach (var filter in InputFilters)
|
|
99
121
|
frame = filter.Run(frame);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
|
|
3
|
+
namespace Adrenak.UniVoice {
|
|
4
|
+
/// <summary>
|
|
5
|
+
/// An audio input implementation that doesn't do anything.
|
|
6
|
+
/// Use this when the device doesn't have any input mode.
|
|
7
|
+
/// This is especially useful when setting up the ClientSession
|
|
8
|
+
/// object on a dedicated server that likely isn't going to have
|
|
9
|
+
/// and mic or other audio capture devices.
|
|
10
|
+
/// </summary>
|
|
11
|
+
public class EmptyAudioInput : IAudioInput {
|
|
12
|
+
public int Frequency => 1;
|
|
13
|
+
|
|
14
|
+
public int ChannelCount => 1;
|
|
15
|
+
|
|
16
|
+
public int SegmentRate => 1;
|
|
17
|
+
|
|
18
|
+
public event Action<AudioFrame> OnFrameReady;
|
|
19
|
+
|
|
20
|
+
public void Dispose() { }
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
using UnityEngine;
|
|
2
|
+
|
|
3
|
+
using Adrenak.UniMic;
|
|
4
|
+
using Adrenak.UniVoice.Networks;
|
|
5
|
+
using Adrenak.UniVoice.Outputs;
|
|
6
|
+
using Adrenak.UniVoice.Inputs;
|
|
7
|
+
using Adrenak.UniVoice.Filters;
|
|
8
|
+
|
|
9
|
+
namespace Adrenak.UniVoice.Samples {
|
|
10
|
+
/// <summary>
|
|
11
|
+
/// To get this setup sample to work, ensure that you have done the following:
|
|
12
|
+
/// - Import Mirror and add the UNIVOICE_NETWORK_MIRROR compilation symbol to your project
|
|
13
|
+
/// - If you want to use RNNoise filter, import RNNoise4Unity into your project and add UNIVOICE_FILTER_RNNOISE4UNITY
|
|
14
|
+
/// - Add this component to the first scene of your Unity project
|
|
15
|
+
///
|
|
16
|
+
/// *** More info on adding and activating non packaged dependencies is here: https://github.com/adrenak/univoice?tab=readme-ov-file#activating-non-packaged-dependencies ***
|
|
17
|
+
///
|
|
18
|
+
/// This is a basic integration script that uses the following to setup UniVoice:
|
|
19
|
+
/// - <see cref="MirrorServer"/>, an implementation of <see cref="IAudioServer{T}"/>
|
|
20
|
+
/// - <see cref="MirrorClient"/>, an implementation of <see cref="IAudioClient{T}"/>
|
|
21
|
+
/// - <see cref="UniMicInput"/>, an implementation of <see cref="IAudioInput"/> that captures audio from a mic
|
|
22
|
+
/// - <see cref="EmptyAudioInput"/>, an implementation of <see cref="IAudioInput"/> that is basically
|
|
23
|
+
/// an idle audio input used when there is no input device
|
|
24
|
+
/// - <see cref="RNNoiseFilter"/>, an implementation of <see cref="IAudioFilter"/> that removes noise from
|
|
25
|
+
/// captured audio.
|
|
26
|
+
/// - <see cref="ConcentusEncodeFilter"/>, an implementation of <see cref="IAudioFilter"/> that encodes captured audio
|
|
27
|
+
/// using Concentus (C# Opus) to reduce the size of audio frames
|
|
28
|
+
/// - <see cref="ConcentusDecodeFilter"/>, an implementation of <see cref="IAudioFilter"/> that decodes incoming audio
|
|
29
|
+
/// using Concentus to decode and make the audio frame playable.
|
|
30
|
+
/// </summary>
|
|
31
|
+
public class UniVoiceMirrorSetupSample : MonoBehaviour {
|
|
32
|
+
const string TAG = "[BasicUniVoiceSetupSample]";
|
|
33
|
+
|
|
34
|
+
/// <summary>
|
|
35
|
+
/// Whether UniVoice has been setup successfully. This field will return true if the setup was successful.
|
|
36
|
+
/// It runs on both server and client.
|
|
37
|
+
/// </summary>
|
|
38
|
+
public static bool HasSetUp { get; private set; }
|
|
39
|
+
|
|
40
|
+
/// <summary>
|
|
41
|
+
/// The server object.
|
|
42
|
+
/// </summary>
|
|
43
|
+
public static IAudioServer<int> AudioServer { get; private set; }
|
|
44
|
+
|
|
45
|
+
/// <summary>
|
|
46
|
+
/// The client session.
|
|
47
|
+
/// </summary>
|
|
48
|
+
public static ClientSession<int> ClientSession { get; private set; }
|
|
49
|
+
|
|
50
|
+
[SerializeField] bool useRNNoise4UnityIfAvailable = true;
|
|
51
|
+
|
|
52
|
+
[SerializeField] bool useConcentusEncodeAndDecode = true;
|
|
53
|
+
|
|
54
|
+
void Start() {
|
|
55
|
+
if (HasSetUp) {
|
|
56
|
+
Debug.unityLogger.Log(LogType.Log, TAG, "UniVoice is already set up. Ignoring...");
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
HasSetUp = Setup();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
bool Setup() {
|
|
63
|
+
Debug.unityLogger.Log(LogType.Log, TAG, "Trying to setup UniVoice");
|
|
64
|
+
|
|
65
|
+
bool failed = false;
|
|
66
|
+
|
|
67
|
+
// Set setup the AudioServer and ClientSession on ALL builds. This means that you'd
|
|
68
|
+
// have a ClientSession on a dedicated server, even though there's not much you can do with it.
|
|
69
|
+
// Similarly, a client would also have an AudioServer object. But it would just be inactive.
|
|
70
|
+
// This sample is for ease of use and to get something working quickly, so we don't bother
|
|
71
|
+
// with these minor details. Note that doing so does not have any performance implications
|
|
72
|
+
// so you can do this, so you could keep this approach without any tradeoffs.
|
|
73
|
+
var createdAudioServer = SetupAudioServer();
|
|
74
|
+
if (!createdAudioServer) {
|
|
75
|
+
Debug.unityLogger.Log(LogType.Error, TAG, "Could not setup UniVoice server.");
|
|
76
|
+
failed = true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
var setupAudioClient = SetupClientSession();
|
|
80
|
+
if (!setupAudioClient) {
|
|
81
|
+
Debug.unityLogger.Log(LogType.Error, TAG, "Could not setup UniVoice client.");
|
|
82
|
+
failed = true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!failed)
|
|
86
|
+
Debug.unityLogger.Log(LogType.Log, TAG, "UniVoice successfully setup!");
|
|
87
|
+
else
|
|
88
|
+
Debug.unityLogger.Log(LogType.Error, TAG, $"Refer to the notes on top of {typeof(UniVoiceMirrorSetupSample).Name}.cs for setup instructions.");
|
|
89
|
+
return !failed;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
bool SetupAudioServer() {
|
|
93
|
+
#if UNIVOICE_NETWORK_MIRROR
|
|
94
|
+
// ---- CREATE AUDIO SERVER AND SUBSCRIBE TO EVENTS TO PRINT LOGS ----
|
|
95
|
+
// We create a server. If this code runs in server mode, MirrorServer will take care
|
|
96
|
+
// or automatically handling all incoming messages. On a device connecting as a client,
|
|
97
|
+
// this code doesn't do anything.
|
|
98
|
+
AudioServer = new MirrorServer();
|
|
99
|
+
Debug.unityLogger.Log(LogType.Log, TAG, "Created MirrorServer object");
|
|
100
|
+
|
|
101
|
+
AudioServer.OnServerStart += () => {
|
|
102
|
+
Debug.unityLogger.Log(LogType.Log, TAG, "Server started");
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
AudioServer.OnServerStop += () => {
|
|
106
|
+
Debug.unityLogger.Log(LogType.Log, TAG, "Server stopped");
|
|
107
|
+
};
|
|
108
|
+
return true;
|
|
109
|
+
#else
|
|
110
|
+
Debug.unityLogger.Log(LogType.Error, TAG, "MirrorServer implementation not found!");
|
|
111
|
+
return false;
|
|
112
|
+
#endif
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
bool SetupClientSession() {
|
|
116
|
+
#if UNIVOICE_NETWORK_MIRROR
|
|
117
|
+
// ---- CREATE AUDIO CLIENT AND SUBSCRIBE TO EVENTS ----
|
|
118
|
+
IAudioClient<int> client = new MirrorClient();
|
|
119
|
+
client.OnJoined += (id, peerIds) => {
|
|
120
|
+
Debug.unityLogger.Log(LogType.Log, TAG, $"You are Peer ID {id} your peers are {string.Join(", ", peerIds)}");
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
client.OnLeft += () => {
|
|
124
|
+
Debug.unityLogger.Log(LogType.Log, TAG, "You left the chatroom");
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// When a peer joins, we instantiate a new peer view
|
|
128
|
+
client.OnPeerJoined += id => {
|
|
129
|
+
Debug.unityLogger.Log(LogType.Log, TAG, $"Peer {id} joined");
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// When a peer leaves, destroy the UI representing them
|
|
133
|
+
client.OnPeerLeft += id => {
|
|
134
|
+
Debug.unityLogger.Log(LogType.Log, TAG, $"Peer {id} left");
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
Debug.unityLogger.Log(LogType.Log, TAG, "Created MirrorClient object");
|
|
138
|
+
|
|
139
|
+
// ---- CREATE AUDIO INPUT ----
|
|
140
|
+
IAudioInput input;
|
|
141
|
+
// Since in this sample we use microphone input via UniMic, we first check if there
|
|
142
|
+
// are any mic devices available.
|
|
143
|
+
Mic.Init(); // Must do this to use the Mic class
|
|
144
|
+
if (Mic.AvailableDevices.Count == 0) {
|
|
145
|
+
Debug.unityLogger.Log(LogType.Log, TAG, "Device has no microphones." +
|
|
146
|
+
"Will only be able to hear other clients, cannot send any audio.");
|
|
147
|
+
input = new EmptyAudioInput();
|
|
148
|
+
Debug.unityLogger.Log(LogType.Log, TAG, "Created EmptyAudioInput");
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
// Get the first recording device that we have available and start it.
|
|
152
|
+
// Then we create a UniMicInput instance that requires the mic object
|
|
153
|
+
// For more info on UniMic refer to https://www.github.com/adrenak/unimic
|
|
154
|
+
var mic = Mic.AvailableDevices[0];
|
|
155
|
+
mic.StartRecording(60);
|
|
156
|
+
Debug.unityLogger.Log(LogType.Log, TAG, "Started recording with Mic device named." +
|
|
157
|
+
mic.Name + $" at frequency {mic.SamplingFrequency} with frame duration {mic.FrameDurationMS} ms.");
|
|
158
|
+
input = new UniMicInput(mic);
|
|
159
|
+
Debug.unityLogger.Log(LogType.Log, TAG, "Created UniMicInput");
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ---- CREATE AUDIO OUTPUT FACTORY ----
|
|
163
|
+
IAudioOutputFactory outputFactory;
|
|
164
|
+
// We want the incoming audio from peers to be played via the StreamedAudioSourceOutput
|
|
165
|
+
// implementation of IAudioSource interface. So we get the factory for it.
|
|
166
|
+
outputFactory = new StreamedAudioSourceOutput.Factory();
|
|
167
|
+
Debug.unityLogger.Log(LogType.Log, TAG, "Using StreamedAudioSourceOutput.Factory as output factory");
|
|
168
|
+
|
|
169
|
+
// ---- CREATE CLIENT SESSION AND ADD FILTERS TO IT ----
|
|
170
|
+
// With the client, input and output factory ready, we create create the client session
|
|
171
|
+
ClientSession = new ClientSession<int>(client, input, outputFactory);
|
|
172
|
+
Debug.unityLogger.Log(LogType.Log, TAG, "Created session");
|
|
173
|
+
|
|
174
|
+
#if UNIVOICE_FILTER_RNNOISE4UNITY
|
|
175
|
+
if(useRNNoise4UnityIfAvailable) {
|
|
176
|
+
// RNNoiseFilter to remove noise from captured audio
|
|
177
|
+
session.InputFilters.Add(new RNNoiseFilter());
|
|
178
|
+
Debug.unityLogger.Log(LogType.Log, TAG, "Registered RNNoiseFilter as an input filter");
|
|
179
|
+
}
|
|
180
|
+
#endif
|
|
181
|
+
|
|
182
|
+
if (useConcentusEncodeAndDecode) {
|
|
183
|
+
// ConcentureEncoder filter to encode captured audio that reduces the audio frame size
|
|
184
|
+
ClientSession.InputFilters.Add(new ConcentusEncodeFilter());
|
|
185
|
+
Debug.unityLogger.Log(LogType.Log, TAG, "Registered ConcentusEncodeFilter as an input filter");
|
|
186
|
+
|
|
187
|
+
// For incoming audio register the ConcentusDecodeFilter to decode the encoded audio received from other clients
|
|
188
|
+
ClientSession.OutputFilters.Add(new ConcentusDecodeFilter());
|
|
189
|
+
Debug.unityLogger.Log(LogType.Log, TAG, "Registered ConcentusDecodeFilter as an output filter");
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return true;
|
|
193
|
+
#else
|
|
194
|
+
Debug.unityLogger.Log(LogType.Error, TAG, "MirrorClient implementation not found!");
|
|
195
|
+
return false;
|
|
196
|
+
#endif
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
%YAML 1.1
|
|
2
|
+
%TAG !u! tag:unity3d.com,2011:
|
|
3
|
+
--- !u!29 &1
|
|
4
|
+
OcclusionCullingSettings:
|
|
5
|
+
m_ObjectHideFlags: 0
|
|
6
|
+
serializedVersion: 2
|
|
7
|
+
m_OcclusionBakeSettings:
|
|
8
|
+
smallestOccluder: 5
|
|
9
|
+
smallestHole: 0.25
|
|
10
|
+
backfaceThreshold: 100
|
|
11
|
+
m_SceneGUID: 00000000000000000000000000000000
|
|
12
|
+
m_OcclusionCullingData: {fileID: 0}
|
|
13
|
+
--- !u!104 &2
|
|
14
|
+
RenderSettings:
|
|
15
|
+
m_ObjectHideFlags: 0
|
|
16
|
+
serializedVersion: 9
|
|
17
|
+
m_Fog: 0
|
|
18
|
+
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
|
|
19
|
+
m_FogMode: 3
|
|
20
|
+
m_FogDensity: 0.01
|
|
21
|
+
m_LinearFogStart: 0
|
|
22
|
+
m_LinearFogEnd: 300
|
|
23
|
+
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
|
|
24
|
+
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
|
|
25
|
+
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
|
|
26
|
+
m_AmbientIntensity: 1
|
|
27
|
+
m_AmbientMode: 0
|
|
28
|
+
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
|
|
29
|
+
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
|
|
30
|
+
m_HaloStrength: 0.5
|
|
31
|
+
m_FlareStrength: 1
|
|
32
|
+
m_FlareFadeSpeed: 3
|
|
33
|
+
m_HaloTexture: {fileID: 0}
|
|
34
|
+
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
|
|
35
|
+
m_DefaultReflectionMode: 0
|
|
36
|
+
m_DefaultReflectionResolution: 128
|
|
37
|
+
m_ReflectionBounces: 1
|
|
38
|
+
m_ReflectionIntensity: 1
|
|
39
|
+
m_CustomReflection: {fileID: 0}
|
|
40
|
+
m_Sun: {fileID: 0}
|
|
41
|
+
m_IndirectSpecularColor: {r: 0.44657874, g: 0.49641275, b: 0.5748172, a: 1}
|
|
42
|
+
m_UseRadianceAmbientProbe: 0
|
|
43
|
+
--- !u!157 &3
|
|
44
|
+
LightmapSettings:
|
|
45
|
+
m_ObjectHideFlags: 0
|
|
46
|
+
serializedVersion: 12
|
|
47
|
+
m_GIWorkflowMode: 1
|
|
48
|
+
m_GISettings:
|
|
49
|
+
serializedVersion: 2
|
|
50
|
+
m_BounceScale: 1
|
|
51
|
+
m_IndirectOutputScale: 1
|
|
52
|
+
m_AlbedoBoost: 1
|
|
53
|
+
m_EnvironmentLightingMode: 0
|
|
54
|
+
m_EnableBakedLightmaps: 1
|
|
55
|
+
m_EnableRealtimeLightmaps: 0
|
|
56
|
+
m_LightmapEditorSettings:
|
|
57
|
+
serializedVersion: 12
|
|
58
|
+
m_Resolution: 2
|
|
59
|
+
m_BakeResolution: 40
|
|
60
|
+
m_AtlasSize: 1024
|
|
61
|
+
m_AO: 0
|
|
62
|
+
m_AOMaxDistance: 1
|
|
63
|
+
m_CompAOExponent: 1
|
|
64
|
+
m_CompAOExponentDirect: 0
|
|
65
|
+
m_ExtractAmbientOcclusion: 0
|
|
66
|
+
m_Padding: 2
|
|
67
|
+
m_LightmapParameters: {fileID: 0}
|
|
68
|
+
m_LightmapsBakeMode: 1
|
|
69
|
+
m_TextureCompression: 1
|
|
70
|
+
m_FinalGather: 0
|
|
71
|
+
m_FinalGatherFiltering: 1
|
|
72
|
+
m_FinalGatherRayCount: 256
|
|
73
|
+
m_ReflectionCompression: 2
|
|
74
|
+
m_MixedBakeMode: 2
|
|
75
|
+
m_BakeBackend: 1
|
|
76
|
+
m_PVRSampling: 1
|
|
77
|
+
m_PVRDirectSampleCount: 32
|
|
78
|
+
m_PVRSampleCount: 512
|
|
79
|
+
m_PVRBounces: 2
|
|
80
|
+
m_PVREnvironmentSampleCount: 256
|
|
81
|
+
m_PVREnvironmentReferencePointCount: 2048
|
|
82
|
+
m_PVRFilteringMode: 1
|
|
83
|
+
m_PVRDenoiserTypeDirect: 1
|
|
84
|
+
m_PVRDenoiserTypeIndirect: 1
|
|
85
|
+
m_PVRDenoiserTypeAO: 1
|
|
86
|
+
m_PVRFilterTypeDirect: 0
|
|
87
|
+
m_PVRFilterTypeIndirect: 0
|
|
88
|
+
m_PVRFilterTypeAO: 0
|
|
89
|
+
m_PVREnvironmentMIS: 1
|
|
90
|
+
m_PVRCulling: 1
|
|
91
|
+
m_PVRFilteringGaussRadiusDirect: 1
|
|
92
|
+
m_PVRFilteringGaussRadiusIndirect: 5
|
|
93
|
+
m_PVRFilteringGaussRadiusAO: 2
|
|
94
|
+
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
|
95
|
+
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
|
96
|
+
m_PVRFilteringAtrousPositionSigmaAO: 1
|
|
97
|
+
m_ExportTrainingData: 0
|
|
98
|
+
m_TrainingDataDestination: TrainingData
|
|
99
|
+
m_LightProbeSampleCountMultiplier: 4
|
|
100
|
+
m_LightingDataAsset: {fileID: 0}
|
|
101
|
+
m_LightingSettings: {fileID: 0}
|
|
102
|
+
--- !u!196 &4
|
|
103
|
+
NavMeshSettings:
|
|
104
|
+
serializedVersion: 2
|
|
105
|
+
m_ObjectHideFlags: 0
|
|
106
|
+
m_BuildSettings:
|
|
107
|
+
serializedVersion: 2
|
|
108
|
+
agentTypeID: 0
|
|
109
|
+
agentRadius: 0.5
|
|
110
|
+
agentHeight: 2
|
|
111
|
+
agentSlope: 45
|
|
112
|
+
agentClimb: 0.4
|
|
113
|
+
ledgeDropHeight: 0
|
|
114
|
+
maxJumpAcrossDistance: 0
|
|
115
|
+
minRegionArea: 2
|
|
116
|
+
manualCellSize: 0
|
|
117
|
+
cellSize: 0.16666667
|
|
118
|
+
manualTileSize: 0
|
|
119
|
+
tileSize: 256
|
|
120
|
+
accuratePlacement: 0
|
|
121
|
+
maxJobWorkers: 0
|
|
122
|
+
preserveTilesOutsideBounds: 0
|
|
123
|
+
debug:
|
|
124
|
+
m_Flags: 0
|
|
125
|
+
m_NavMeshData: {fileID: 0}
|
|
126
|
+
--- !u!1 &169645566
|
|
127
|
+
GameObject:
|
|
128
|
+
m_ObjectHideFlags: 0
|
|
129
|
+
m_CorrespondingSourceObject: {fileID: 0}
|
|
130
|
+
m_PrefabInstance: {fileID: 0}
|
|
131
|
+
m_PrefabAsset: {fileID: 0}
|
|
132
|
+
serializedVersion: 6
|
|
133
|
+
m_Component:
|
|
134
|
+
- component: {fileID: 169645568}
|
|
135
|
+
- component: {fileID: 169645567}
|
|
136
|
+
m_Layer: 0
|
|
137
|
+
m_Name: Directional Light
|
|
138
|
+
m_TagString: Untagged
|
|
139
|
+
m_Icon: {fileID: 0}
|
|
140
|
+
m_NavMeshLayer: 0
|
|
141
|
+
m_StaticEditorFlags: 0
|
|
142
|
+
m_IsActive: 1
|
|
143
|
+
--- !u!108 &169645567
|
|
144
|
+
Light:
|
|
145
|
+
m_ObjectHideFlags: 0
|
|
146
|
+
m_CorrespondingSourceObject: {fileID: 0}
|
|
147
|
+
m_PrefabInstance: {fileID: 0}
|
|
148
|
+
m_PrefabAsset: {fileID: 0}
|
|
149
|
+
m_GameObject: {fileID: 169645566}
|
|
150
|
+
m_Enabled: 1
|
|
151
|
+
serializedVersion: 10
|
|
152
|
+
m_Type: 1
|
|
153
|
+
m_Shape: 0
|
|
154
|
+
m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
|
|
155
|
+
m_Intensity: 1
|
|
156
|
+
m_Range: 10
|
|
157
|
+
m_SpotAngle: 30
|
|
158
|
+
m_InnerSpotAngle: 21.80208
|
|
159
|
+
m_CookieSize: 10
|
|
160
|
+
m_Shadows:
|
|
161
|
+
m_Type: 2
|
|
162
|
+
m_Resolution: -1
|
|
163
|
+
m_CustomResolution: -1
|
|
164
|
+
m_Strength: 1
|
|
165
|
+
m_Bias: 0.05
|
|
166
|
+
m_NormalBias: 0.4
|
|
167
|
+
m_NearPlane: 0.2
|
|
168
|
+
m_CullingMatrixOverride:
|
|
169
|
+
e00: 1
|
|
170
|
+
e01: 0
|
|
171
|
+
e02: 0
|
|
172
|
+
e03: 0
|
|
173
|
+
e10: 0
|
|
174
|
+
e11: 1
|
|
175
|
+
e12: 0
|
|
176
|
+
e13: 0
|
|
177
|
+
e20: 0
|
|
178
|
+
e21: 0
|
|
179
|
+
e22: 1
|
|
180
|
+
e23: 0
|
|
181
|
+
e30: 0
|
|
182
|
+
e31: 0
|
|
183
|
+
e32: 0
|
|
184
|
+
e33: 1
|
|
185
|
+
m_UseCullingMatrixOverride: 0
|
|
186
|
+
m_Cookie: {fileID: 0}
|
|
187
|
+
m_DrawHalo: 0
|
|
188
|
+
m_Flare: {fileID: 0}
|
|
189
|
+
m_RenderMode: 0
|
|
190
|
+
m_CullingMask:
|
|
191
|
+
serializedVersion: 2
|
|
192
|
+
m_Bits: 4294967295
|
|
193
|
+
m_RenderingLayerMask: 1
|
|
194
|
+
m_Lightmapping: 4
|
|
195
|
+
m_LightShadowCasterMode: 0
|
|
196
|
+
m_AreaSize: {x: 1, y: 1}
|
|
197
|
+
m_BounceIntensity: 1
|
|
198
|
+
m_ColorTemperature: 6570
|
|
199
|
+
m_UseColorTemperature: 0
|
|
200
|
+
m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
|
|
201
|
+
m_UseBoundingSphereOverride: 0
|
|
202
|
+
m_UseViewFrustumForShadowCasterCull: 1
|
|
203
|
+
m_ShadowRadius: 0
|
|
204
|
+
m_ShadowAngle: 0
|
|
205
|
+
--- !u!4 &169645568
|
|
206
|
+
Transform:
|
|
207
|
+
m_ObjectHideFlags: 0
|
|
208
|
+
m_CorrespondingSourceObject: {fileID: 0}
|
|
209
|
+
m_PrefabInstance: {fileID: 0}
|
|
210
|
+
m_PrefabAsset: {fileID: 0}
|
|
211
|
+
m_GameObject: {fileID: 169645566}
|
|
212
|
+
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
|
|
213
|
+
m_LocalPosition: {x: 0, y: 3, z: 0}
|
|
214
|
+
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
215
|
+
m_ConstrainProportionsScale: 0
|
|
216
|
+
m_Children: []
|
|
217
|
+
m_Father: {fileID: 0}
|
|
218
|
+
m_RootOrder: 1
|
|
219
|
+
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
|
|
220
|
+
--- !u!1 &419491085
|
|
221
|
+
GameObject:
|
|
222
|
+
m_ObjectHideFlags: 0
|
|
223
|
+
m_CorrespondingSourceObject: {fileID: 0}
|
|
224
|
+
m_PrefabInstance: {fileID: 0}
|
|
225
|
+
m_PrefabAsset: {fileID: 0}
|
|
226
|
+
serializedVersion: 6
|
|
227
|
+
m_Component:
|
|
228
|
+
- component: {fileID: 419491088}
|
|
229
|
+
- component: {fileID: 419491087}
|
|
230
|
+
- component: {fileID: 419491086}
|
|
231
|
+
m_Layer: 0
|
|
232
|
+
m_Name: Main Camera
|
|
233
|
+
m_TagString: MainCamera
|
|
234
|
+
m_Icon: {fileID: 0}
|
|
235
|
+
m_NavMeshLayer: 0
|
|
236
|
+
m_StaticEditorFlags: 0
|
|
237
|
+
m_IsActive: 1
|
|
238
|
+
--- !u!81 &419491086
|
|
239
|
+
AudioListener:
|
|
240
|
+
m_ObjectHideFlags: 0
|
|
241
|
+
m_CorrespondingSourceObject: {fileID: 0}
|
|
242
|
+
m_PrefabInstance: {fileID: 0}
|
|
243
|
+
m_PrefabAsset: {fileID: 0}
|
|
244
|
+
m_GameObject: {fileID: 419491085}
|
|
245
|
+
m_Enabled: 1
|
|
246
|
+
--- !u!20 &419491087
|
|
247
|
+
Camera:
|
|
248
|
+
m_ObjectHideFlags: 0
|
|
249
|
+
m_CorrespondingSourceObject: {fileID: 0}
|
|
250
|
+
m_PrefabInstance: {fileID: 0}
|
|
251
|
+
m_PrefabAsset: {fileID: 0}
|
|
252
|
+
m_GameObject: {fileID: 419491085}
|
|
253
|
+
m_Enabled: 1
|
|
254
|
+
serializedVersion: 2
|
|
255
|
+
m_ClearFlags: 1
|
|
256
|
+
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
|
|
257
|
+
m_projectionMatrixMode: 1
|
|
258
|
+
m_GateFitMode: 2
|
|
259
|
+
m_FOVAxisMode: 0
|
|
260
|
+
m_SensorSize: {x: 36, y: 24}
|
|
261
|
+
m_LensShift: {x: 0, y: 0}
|
|
262
|
+
m_FocalLength: 50
|
|
263
|
+
m_NormalizedViewPortRect:
|
|
264
|
+
serializedVersion: 2
|
|
265
|
+
x: 0
|
|
266
|
+
y: 0
|
|
267
|
+
width: 1
|
|
268
|
+
height: 1
|
|
269
|
+
near clip plane: 0.3
|
|
270
|
+
far clip plane: 1000
|
|
271
|
+
field of view: 60
|
|
272
|
+
orthographic: 0
|
|
273
|
+
orthographic size: 5
|
|
274
|
+
m_Depth: -1
|
|
275
|
+
m_CullingMask:
|
|
276
|
+
serializedVersion: 2
|
|
277
|
+
m_Bits: 4294967295
|
|
278
|
+
m_RenderingPath: -1
|
|
279
|
+
m_TargetTexture: {fileID: 0}
|
|
280
|
+
m_TargetDisplay: 0
|
|
281
|
+
m_TargetEye: 3
|
|
282
|
+
m_HDR: 1
|
|
283
|
+
m_AllowMSAA: 1
|
|
284
|
+
m_AllowDynamicResolution: 0
|
|
285
|
+
m_ForceIntoRT: 0
|
|
286
|
+
m_OcclusionCulling: 1
|
|
287
|
+
m_StereoConvergence: 10
|
|
288
|
+
m_StereoSeparation: 0.022
|
|
289
|
+
--- !u!4 &419491088
|
|
290
|
+
Transform:
|
|
291
|
+
m_ObjectHideFlags: 0
|
|
292
|
+
m_CorrespondingSourceObject: {fileID: 0}
|
|
293
|
+
m_PrefabInstance: {fileID: 0}
|
|
294
|
+
m_PrefabAsset: {fileID: 0}
|
|
295
|
+
m_GameObject: {fileID: 419491085}
|
|
296
|
+
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
297
|
+
m_LocalPosition: {x: 0, y: 1, z: -10}
|
|
298
|
+
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
299
|
+
m_ConstrainProportionsScale: 0
|
|
300
|
+
m_Children: []
|
|
301
|
+
m_Father: {fileID: 0}
|
|
302
|
+
m_RootOrder: 0
|
|
303
|
+
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
304
|
+
--- !u!1 &1902381426
|
|
305
|
+
GameObject:
|
|
306
|
+
m_ObjectHideFlags: 0
|
|
307
|
+
m_CorrespondingSourceObject: {fileID: 0}
|
|
308
|
+
m_PrefabInstance: {fileID: 0}
|
|
309
|
+
m_PrefabAsset: {fileID: 0}
|
|
310
|
+
serializedVersion: 6
|
|
311
|
+
m_Component:
|
|
312
|
+
- component: {fileID: 1902381428}
|
|
313
|
+
- component: {fileID: 1902381427}
|
|
314
|
+
- component: {fileID: 1902381429}
|
|
315
|
+
- component: {fileID: 1902381430}
|
|
316
|
+
- component: {fileID: 1902381431}
|
|
317
|
+
m_Layer: 0
|
|
318
|
+
m_Name: NetworkManager
|
|
319
|
+
m_TagString: Untagged
|
|
320
|
+
m_Icon: {fileID: 0}
|
|
321
|
+
m_NavMeshLayer: 0
|
|
322
|
+
m_StaticEditorFlags: 0
|
|
323
|
+
m_IsActive: 1
|
|
324
|
+
--- !u!114 &1902381427
|
|
325
|
+
MonoBehaviour:
|
|
326
|
+
m_ObjectHideFlags: 0
|
|
327
|
+
m_CorrespondingSourceObject: {fileID: 0}
|
|
328
|
+
m_PrefabInstance: {fileID: 0}
|
|
329
|
+
m_PrefabAsset: {fileID: 0}
|
|
330
|
+
m_GameObject: {fileID: 1902381426}
|
|
331
|
+
m_Enabled: 1
|
|
332
|
+
m_EditorHideFlags: 0
|
|
333
|
+
m_Script: {fileID: 11500000, guid: 8aab4c8111b7c411b9b92cf3dbc5bd4e, type: 3}
|
|
334
|
+
m_Name:
|
|
335
|
+
m_EditorClassIdentifier:
|
|
336
|
+
dontDestroyOnLoad: 1
|
|
337
|
+
runInBackground: 1
|
|
338
|
+
headlessStartMode: 1
|
|
339
|
+
editorAutoStart: 0
|
|
340
|
+
sendRate: 60
|
|
341
|
+
offlineScene:
|
|
342
|
+
onlineScene:
|
|
343
|
+
offlineSceneLoadDelay: 0
|
|
344
|
+
transport: {fileID: 1902381429}
|
|
345
|
+
networkAddress: localhost
|
|
346
|
+
maxConnections: 100
|
|
347
|
+
disconnectInactiveConnections: 0
|
|
348
|
+
disconnectInactiveTimeout: 60
|
|
349
|
+
authenticator: {fileID: 0}
|
|
350
|
+
playerPrefab: {fileID: 0}
|
|
351
|
+
autoCreatePlayer: 0
|
|
352
|
+
playerSpawnMethod: 0
|
|
353
|
+
spawnPrefabs: []
|
|
354
|
+
exceptionsDisconnect: 1
|
|
355
|
+
snapshotSettings:
|
|
356
|
+
bufferTimeMultiplier: 2
|
|
357
|
+
bufferLimit: 32
|
|
358
|
+
catchupNegativeThreshold: -1
|
|
359
|
+
catchupPositiveThreshold: 1
|
|
360
|
+
catchupSpeed: 0.019999999552965164
|
|
361
|
+
slowdownSpeed: 0.03999999910593033
|
|
362
|
+
driftEmaDuration: 1
|
|
363
|
+
dynamicAdjustment: 1
|
|
364
|
+
dynamicAdjustmentTolerance: 1
|
|
365
|
+
deliveryTimeEmaDuration: 2
|
|
366
|
+
evaluationMethod: 0
|
|
367
|
+
evaluationInterval: 3
|
|
368
|
+
timeInterpolationGui: 0
|
|
369
|
+
--- !u!4 &1902381428
|
|
370
|
+
Transform:
|
|
371
|
+
m_ObjectHideFlags: 0
|
|
372
|
+
m_CorrespondingSourceObject: {fileID: 0}
|
|
373
|
+
m_PrefabInstance: {fileID: 0}
|
|
374
|
+
m_PrefabAsset: {fileID: 0}
|
|
375
|
+
m_GameObject: {fileID: 1902381426}
|
|
376
|
+
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
377
|
+
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
378
|
+
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
379
|
+
m_ConstrainProportionsScale: 0
|
|
380
|
+
m_Children: []
|
|
381
|
+
m_Father: {fileID: 0}
|
|
382
|
+
m_RootOrder: 2
|
|
383
|
+
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
384
|
+
--- !u!114 &1902381429
|
|
385
|
+
MonoBehaviour:
|
|
386
|
+
m_ObjectHideFlags: 0
|
|
387
|
+
m_CorrespondingSourceObject: {fileID: 0}
|
|
388
|
+
m_PrefabInstance: {fileID: 0}
|
|
389
|
+
m_PrefabAsset: {fileID: 0}
|
|
390
|
+
m_GameObject: {fileID: 1902381426}
|
|
391
|
+
m_Enabled: 1
|
|
392
|
+
m_EditorHideFlags: 0
|
|
393
|
+
m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
|
|
394
|
+
m_Name:
|
|
395
|
+
m_EditorClassIdentifier:
|
|
396
|
+
port: 7777
|
|
397
|
+
NoDelay: 1
|
|
398
|
+
SendTimeout: 5000
|
|
399
|
+
ReceiveTimeout: 30000
|
|
400
|
+
serverMaxMessageSize: 16384
|
|
401
|
+
serverMaxReceivesPerTick: 10000
|
|
402
|
+
serverSendQueueLimitPerConnection: 10000
|
|
403
|
+
serverReceiveQueueLimitPerConnection: 10000
|
|
404
|
+
clientMaxMessageSize: 16384
|
|
405
|
+
clientMaxReceivesPerTick: 1000
|
|
406
|
+
clientSendQueueLimit: 10000
|
|
407
|
+
clientReceiveQueueLimit: 10000
|
|
408
|
+
--- !u!114 &1902381430
|
|
409
|
+
MonoBehaviour:
|
|
410
|
+
m_ObjectHideFlags: 0
|
|
411
|
+
m_CorrespondingSourceObject: {fileID: 0}
|
|
412
|
+
m_PrefabInstance: {fileID: 0}
|
|
413
|
+
m_PrefabAsset: {fileID: 0}
|
|
414
|
+
m_GameObject: {fileID: 1902381426}
|
|
415
|
+
m_Enabled: 1
|
|
416
|
+
m_EditorHideFlags: 0
|
|
417
|
+
m_Script: {fileID: 11500000, guid: d0dec1d2df214b44f8cb106b071695ce, type: 3}
|
|
418
|
+
m_Name:
|
|
419
|
+
m_EditorClassIdentifier:
|
|
420
|
+
useRNNoise4UnityIfAvailable: 1
|
|
421
|
+
useConcentusEncodeAndDecode: 1
|
|
422
|
+
--- !u!114 &1902381431
|
|
423
|
+
MonoBehaviour:
|
|
424
|
+
m_ObjectHideFlags: 0
|
|
425
|
+
m_CorrespondingSourceObject: {fileID: 0}
|
|
426
|
+
m_PrefabInstance: {fileID: 0}
|
|
427
|
+
m_PrefabAsset: {fileID: 0}
|
|
428
|
+
m_GameObject: {fileID: 1902381426}
|
|
429
|
+
m_Enabled: 1
|
|
430
|
+
m_EditorHideFlags: 0
|
|
431
|
+
m_Script: {fileID: 11500000, guid: 6442dc8070ceb41f094e44de0bf87274, type: 3}
|
|
432
|
+
m_Name:
|
|
433
|
+
m_EditorClassIdentifier:
|
|
434
|
+
offsetX: 0
|
|
435
|
+
offsetY: 0
|