using UnityEngine; using UnityEngine.UI; using UnityEngine.Video; using UnityEngine.EventSystems; using Fusion; using System.Collections; using System.Collections.Generic; public class VideoPlayerManager : NetworkBehaviour { public VideoPlayer videoPlayer; public RawImage raw; public Material sample; public GameObject loadingScreen; public Slider videoSlider; public Image play; public GameObject cast; public Transform startPoint; public Transform Player; private GameObject nearestTV; public float detectionRadius = 4f; public LineRenderer lineRenderer; private float lastSyncTime = 0f; private bool isDraggingSlider = false; public string videoUrl; [Networked] private bool isPlaying { get; set; } [Networked] private float videoTime { get; set; } void Start() { if (videoPlayer == null) videoPlayer = GetComponent(); videoPlayer.loopPointReached += OnVideoFinished; if (lineRenderer == null) { lineRenderer = gameObject.AddComponent(); lineRenderer.startWidth = 0.05f; lineRenderer.endWidth = 0.05f; lineRenderer.positionCount = 20; lineRenderer.material = new Material(Shader.Find("Sprites/Default")); lineRenderer.material.color = Color.yellow; } raw.material = new Material(sample); RenderTexture renderTexture = new RenderTexture(1920, 1080, 16); videoPlayer.targetTexture = renderTexture; raw.texture = renderTexture; // Slider drag listeners AddSliderDragHandlers(); videoSlider.onValueChanged.AddListener(OnSliderValueChanged); } void Update() { if (!isDraggingSlider && videoPlayer.isPlaying) { videoSlider.value = (float)videoPlayer.time; } play.color = videoPlayer.isPlaying ? Color.green : Color.white; cast.SetActive(nearestTV); FindNearestTV(); if (nearestTV != null) DrawCurvedLine(); else lineRenderer.enabled = false; // Sync play state if (videoPlayer.isPlaying != isPlaying) { if (isPlaying) StartCoroutine(StartVideo()); else videoPlayer.Pause(); } } private IEnumerator StartVideo() { videoPlayer.Prepare(); while (!videoPlayer.isPrepared) { yield return null; } loadingScreen.SetActive(false); videoSlider.minValue = 0; videoSlider.maxValue = (float)videoPlayer.length; videoPlayer.Play(); } public void send() { if (Object.HasStateAuthority) { Play(); InvokeRepeating(nameof(SyncVideoTime), 5f, 5f); } } public void Cast() { if (Object.HasStateAuthority && nearestTV != null) { RPC_SetScreenTexture(Object.Id, nearestTV.GetComponent().Id); } } public void Play() { if (Object.HasStateAuthority) { RPC_TogglePlayPause(videoUrl); } } [Rpc(RpcSources.All, RpcTargets.All)] private void RPC_TogglePlayPause(string url) { videoUrl = url; if (!string.IsNullOrEmpty(videoUrl) && url != videoPlayer.url) { Player.parent.gameObject.SetActive(true); Player.gameObject.SetActive(true); loadingScreen.SetActive(true); videoPlayer.url = videoUrl; } isPlaying = !isPlaying; videoTime = (float)videoPlayer.time; RPC_SyncVideoState(isPlaying, videoTime); } [Rpc(RpcSources.StateAuthority, RpcTargets.All)] private void RPC_SyncVideoState(bool playState, float syncTime) { isPlaying = playState; videoTime = syncTime; videoPlayer.time = syncTime; if (isPlaying) videoPlayer.Play(); else videoPlayer.Pause(); } private void SyncVideoTime() { if (Object.HasStateAuthority && videoPlayer.isPlaying) { float currentTime = (float)videoPlayer.time; RPC_SyncVideoState(isPlaying, currentTime); } } [Rpc(RpcSources.StateAuthority, RpcTargets.All)] private void RPC_SetScreenTexture(NetworkId playerId, NetworkId tvId) { GameObject[] allTVs = GameObject.FindGameObjectsWithTag("tv"); foreach (var tv in allTVs) { if (tv.GetComponent().Id == tvId) { RawImage tvScreen = tv.GetComponentInChildren(); if (tvScreen != null) { tvScreen.texture = raw.texture; tvScreen.material = raw.material; } } } } private void FindNearestTV() { GameObject[] tvObjects = GameObject.FindGameObjectsWithTag("tv"); float minDistance = detectionRadius; nearestTV = null; foreach (var tv in tvObjects) { float distance = Vector3.Distance(transform.position, tv.transform.position); if (distance < minDistance) { minDistance = distance; nearestTV = tv; } } } private void DrawCurvedLine() { if (nearestTV == null || startPoint == null) return; lineRenderer.enabled = true; Vector3 start = startPoint.position; Vector3 end = nearestTV.transform.position; Vector3 middle = (start + end) / 2 + Vector3.up * 1; List curvePoints = new List(); for (float t = 0; t <= 1; t += 0.05f) { Vector3 point = Mathf.Pow(1 - t, 2) * start + 2 * (1 - t) * t * middle + Mathf.Pow(t, 2) * end; curvePoints.Add(point); } lineRenderer.positionCount = curvePoints.Count; lineRenderer.SetPositions(curvePoints.ToArray()); } private void OnVideoFinished(VideoPlayer vp) { isPlaying = false; } public void Show(string u) { videoUrl = u; Invoke("send", 1); } public void OnSliderValueChanged(float value) { if (isDraggingSlider) { videoPlayer.time = value; } } private void AddSliderDragHandlers() { EventTrigger trigger = videoSlider.gameObject.GetComponent(); if (trigger == null) trigger = videoSlider.gameObject.AddComponent(); trigger.triggers = new List(); // Pointer Down EventTrigger.Entry entryDown = new EventTrigger.Entry(); entryDown.eventID = EventTriggerType.PointerDown; entryDown.callback.AddListener((data) => { isDraggingSlider = true; }); trigger.triggers.Add(entryDown); // Pointer Up EventTrigger.Entry entryUp = new EventTrigger.Entry(); entryUp.eventID = EventTriggerType.PointerUp; entryUp.callback.AddListener((data) => { isDraggingSlider = false; if (Object.HasStateAuthority) { videoTime = (float)videoPlayer.time; RPC_SyncVideoState(isPlaying, videoTime); } }); trigger.triggers.Add(entryUp); } }