deltavr multiplayer 2.0
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
using FishNet.Connection;
|
||||
using FishNet.Object;
|
||||
using UnityEngine;
|
||||
|
||||
namespace _PROJECT.Components.Drawing
|
||||
{
|
||||
public class NetworkDrawingManager : NetworkBehaviour
|
||||
{
|
||||
private TextureDrawing _textureDrawing;
|
||||
|
||||
public override void OnStartServer()
|
||||
{
|
||||
base.OnStartServer();
|
||||
_textureDrawing = GetComponent<TextureDrawing>();
|
||||
}
|
||||
|
||||
[ServerRpc(RequireOwnership = false)]
|
||||
public void RequestDrawOnTextureRPC(Vector2 textureCoord, Color drawColor, int brushSize, Vector3 angle)
|
||||
{
|
||||
DrawOnTextureRPC(textureCoord, drawColor, brushSize, angle);
|
||||
}
|
||||
|
||||
public override void OnStartClient()
|
||||
{
|
||||
base.OnStartClient();
|
||||
_textureDrawing = GetComponent<TextureDrawing>();
|
||||
}
|
||||
|
||||
[ServerRpc(RequireOwnership = false)]
|
||||
public void RequestCurrentTextureRPC(NetworkConnection conn = null)
|
||||
{
|
||||
if (_textureDrawing == null)
|
||||
return;
|
||||
|
||||
SendCurrentTextureRPC(conn, _textureDrawing.initialDrawingTexture);
|
||||
}
|
||||
|
||||
[TargetRpc]
|
||||
private void SendCurrentTextureRPC(NetworkConnection conn, Texture2D currentTexture)
|
||||
{
|
||||
if (_textureDrawing == null)
|
||||
return;
|
||||
|
||||
_textureDrawing.SetTempTexture(currentTexture);
|
||||
}
|
||||
|
||||
[ObserversRpc]
|
||||
private void DrawOnTextureRPC(Vector2 textureCoord, Color drawColor, int brushSize, Vector3 angle)
|
||||
{
|
||||
if (_textureDrawing == null)
|
||||
return;
|
||||
|
||||
_textureDrawing.DrawOnTexture(textureCoord, drawColor, brushSize, angle);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7ec79347d9e4eb4390a702993102f60
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
95
Assets/_PROJECT/Components/Drawing/Scripts/SprayGun.cs
Normal file
95
Assets/_PROJECT/Components/Drawing/Scripts/SprayGun.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.Interaction.Toolkit;
|
||||
|
||||
namespace _PROJECT.Components.Drawing
|
||||
{
|
||||
public class SprayGun : XRGrabInteractable
|
||||
{
|
||||
public GameObject trigger;
|
||||
public ParticleSystem sprayPart;
|
||||
public Transform sprayPoint;
|
||||
public float maxDistance = 0.5f;
|
||||
|
||||
public Color sprayColor;
|
||||
public int spraySize = 100;
|
||||
|
||||
private int _layerMask;
|
||||
|
||||
private float _cooldownTimer = 0f;
|
||||
private bool _isSpraying;
|
||||
|
||||
protected override void OnActivated(ActivateEventArgs args)
|
||||
{
|
||||
base.OnActivated(args);
|
||||
StartSpray();
|
||||
}
|
||||
|
||||
protected override void OnDeactivated(DeactivateEventArgs args)
|
||||
{
|
||||
base.OnDeactivated(args);
|
||||
StopSpray();
|
||||
}
|
||||
|
||||
private new void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
sprayPart.Stop(true, ParticleSystemStopBehavior.StopEmitting);
|
||||
_isSpraying = false;
|
||||
_layerMask = 1 << LayerMask.NameToLayer("Paintable");
|
||||
}
|
||||
|
||||
private void StartSpray()
|
||||
{
|
||||
_isSpraying = true;
|
||||
trigger.transform.Rotate(0f, 0f, -8.5f);
|
||||
sprayPart.Play(true);
|
||||
}
|
||||
|
||||
private void StopSpray()
|
||||
{
|
||||
_isSpraying = false;
|
||||
trigger.transform.Rotate(0f, 0f, 8.5f);
|
||||
sprayPart.Stop(true, ParticleSystemStopBehavior.StopEmitting);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!isSelected || !_isSpraying)
|
||||
{
|
||||
if (!sprayPart.isPlaying) return;
|
||||
sprayPart.Stop(true, ParticleSystemStopBehavior.StopEmitting);
|
||||
_isSpraying = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_cooldownTimer > 0f)
|
||||
{
|
||||
_cooldownTimer -= Time.deltaTime;
|
||||
return;
|
||||
}
|
||||
|
||||
RaycastHit hit;
|
||||
if (!Physics.Raycast(sprayPoint.position, sprayPoint.forward, out hit, maxDistance, _layerMask))
|
||||
{
|
||||
Debug.Log("No hit");
|
||||
Debug.DrawLine(sprayPoint.position, sprayPoint.position + sprayPoint.forward * maxDistance, Color.red);
|
||||
_cooldownTimer = 0.1f;
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("Hit " + hit.collider.name);
|
||||
Debug.DrawLine(sprayPoint.position, hit.point, Color.green); // Draw a line in the scene view
|
||||
|
||||
TextureDrawing textureDrawing = hit.collider.GetComponent<TextureDrawing>();
|
||||
if (textureDrawing == null) return;
|
||||
Vector2 textureCoord = hit.textureCoord;
|
||||
|
||||
// Calculate the spray size based on the distance from the spray point to the hit point
|
||||
int adjustedSpraySize = Mathf.RoundToInt(Mathf.Lerp(0f, spraySize,
|
||||
Vector3.Distance(sprayPoint.position, hit.point) / maxDistance));
|
||||
_cooldownTimer = 0.05f;
|
||||
|
||||
textureDrawing.Draw(textureCoord, sprayColor, adjustedSpraySize, sprayPoint.forward);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/_PROJECT/Components/Drawing/Scripts/SprayGun.cs.meta
Normal file
11
Assets/_PROJECT/Components/Drawing/Scripts/SprayGun.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42a941046a5ce854db60fb229b725438
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,45 @@
|
||||
using FishNet.Serializing;
|
||||
using UnityEngine;
|
||||
|
||||
namespace _PROJECT.Components.Drawing
|
||||
{
|
||||
public static class Texture2DSerializer
|
||||
{
|
||||
public static void WriteTexture2D(this Writer writer, Texture2D texture)
|
||||
{
|
||||
// Convert the Texture2D to a byte array using PNG format
|
||||
byte[] textureBytes = texture.EncodeToPNG();
|
||||
|
||||
// Write the length of the byte array
|
||||
writer.WriteInt32(textureBytes.Length);
|
||||
|
||||
// Write the byte array
|
||||
writer.WriteBytes(textureBytes, 0, textureBytes.Length);
|
||||
}
|
||||
|
||||
public static Texture2D ReadTexture2D(this Reader reader)
|
||||
{
|
||||
// Read the length of the byte array
|
||||
int textureBytesLength = reader.ReadInt32();
|
||||
|
||||
// Create a new byte array with the length
|
||||
byte[] textureBytes = new byte[textureBytesLength];
|
||||
|
||||
// Read the byte array into the created buffer
|
||||
reader.ReadBytes(ref textureBytes, textureBytesLength);
|
||||
|
||||
// Create a new Texture2D object
|
||||
Texture2D texture = new Texture2D(1024, 1024);
|
||||
|
||||
// Load the texture data from the byte array
|
||||
if (texture.LoadImage(textureBytes))
|
||||
{
|
||||
// Return the reconstructed Texture2D
|
||||
return texture;
|
||||
}
|
||||
|
||||
Debug.LogError("Failed to load texture from byte array");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5d5c913102484994c83121571a6fe95d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
89
Assets/_PROJECT/Components/Drawing/Scripts/TextureDrawing.cs
Normal file
89
Assets/_PROJECT/Components/Drawing/Scripts/TextureDrawing.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace _PROJECT.Components.Drawing
|
||||
{
|
||||
public class TextureDrawing : MonoBehaviour
|
||||
{
|
||||
public Texture2D initialDrawingTexture;
|
||||
private MeshRenderer _meshRenderer;
|
||||
private Texture2D _tempTexture;
|
||||
public float maxBrushSize = 100f;
|
||||
|
||||
public NetworkDrawingManager networkDrawingManager;
|
||||
|
||||
void Start()
|
||||
{
|
||||
_meshRenderer = GetComponent<MeshRenderer>();
|
||||
networkDrawingManager = GetComponent<NetworkDrawingManager>();
|
||||
|
||||
Vector3 scale = transform.lossyScale;
|
||||
|
||||
_tempTexture = ResizeTexture(initialDrawingTexture, Mathf.RoundToInt(scale.x * initialDrawingTexture.width), Mathf.RoundToInt(scale.y * initialDrawingTexture.height));
|
||||
|
||||
_meshRenderer.material.mainTexture = _tempTexture;
|
||||
}
|
||||
|
||||
public void SetTempTexture(Texture2D texture)
|
||||
{
|
||||
_tempTexture = texture;
|
||||
_meshRenderer.material.mainTexture = _tempTexture;
|
||||
}
|
||||
|
||||
public void Draw(Vector2 textureCoord, Color color, int size, Vector3 angle) {
|
||||
networkDrawingManager.RequestDrawOnTextureRPC(textureCoord, color, size, angle);
|
||||
}
|
||||
|
||||
public void DrawOnTexture(Vector2 textureCoord, Color color, int size, Vector3 angle)
|
||||
{
|
||||
int x = Mathf.FloorToInt(textureCoord.x * _tempTexture.width);
|
||||
int y = Mathf.FloorToInt(textureCoord.y * _tempTexture.height);
|
||||
|
||||
float sprayAngle = Mathf.Atan2(angle.y, angle.x) * Mathf.Rad2Deg;
|
||||
Quaternion rotation = Quaternion.AngleAxis(sprayAngle, Vector3.forward);
|
||||
|
||||
float density = Mathf.Lerp(1.0f, 0.1f, size / maxBrushSize);
|
||||
|
||||
float radius = size * density;
|
||||
int numPixels = Mathf.RoundToInt(Mathf.PI * radius * radius);
|
||||
|
||||
for (int i = 0; i < numPixels; i++)
|
||||
{
|
||||
Vector2 offset = new Vector2(Random.Range(-size, size), Random.Range(-size, size));
|
||||
if (offset.magnitude > size) continue;
|
||||
offset = rotation * offset;
|
||||
|
||||
float alpha = Random.Range(0f, 1f);
|
||||
Color sprayColor = new Color(color.r, color.g, color.b, alpha * color.a);
|
||||
|
||||
_tempTexture.SetPixel(x + Mathf.RoundToInt(offset.x), y + Mathf.RoundToInt(offset.y), sprayColor);
|
||||
}
|
||||
|
||||
_tempTexture.Apply();
|
||||
}
|
||||
|
||||
private Texture2D ResizeTexture(Texture2D inputTexture, int newWidth, int newHeight)
|
||||
{
|
||||
Texture2D outputTexture = new Texture2D(newWidth, newHeight);
|
||||
Color[] pixels = new Color[newWidth * newHeight];
|
||||
|
||||
// Resample the input texture to the new size
|
||||
for (int y = 0; y < newHeight; y++)
|
||||
{
|
||||
for (int x = 0; x < newWidth; x++)
|
||||
{
|
||||
float u = x / (float)newWidth;
|
||||
float v = y / (float)newHeight;
|
||||
|
||||
pixels[y * newWidth + x] = inputTexture.GetPixelBilinear(u, v);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the pixels of the output texture
|
||||
outputTexture.SetPixels(pixels);
|
||||
outputTexture.Apply();
|
||||
|
||||
return outputTexture;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a30f50e0a4b8057418d3c0af63996dbb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user