public static IDisposable OnForward(this INetworkTimeline timeline, Func <IEntity, UserInputData[], Fix64, IUserInputResult[]> onNext) { Func <ForwardTimelineData, IUserInputResult[]> func = data => { return(onNext(data.Entity, data.UserInputData[0], data.DeltaTime)); }; return(timeline.OnForward(func)); }
public override void OnEnable() { base.OnEnable(); Physics.autoSimulation = false; NetwrokTimeline.OnForward(_ => { Physics.Simulate(Time.fixedDeltaTime); return(null); }).AddTo(this.Disposer); }
public override void OnEnable() { base.OnEnable(); BulletComponents.OnAdd().Subscribe(entity => { var bulletComponent = entity.GetComponent <BulletComponent>(); var viewComponent = entity.GetComponent <ViewComponent>(); var capsuleCollider = entity.GetComponent <CapsuleCollider>(); bulletComponent.radius = 0.5f * Mathf.Max(2 * capsuleCollider.radius, capsuleCollider.height); }).AddTo(this.Disposer); NetwrokTimeline.OnForward(data => { var bulletComponent = data.Entity.GetComponent <BulletComponent>(); var viewComponent = data.Entity.GetComponent <ViewComponent>(); var capsuleCollider = data.Entity.GetComponent <CapsuleCollider>(); if (bulletComponent.velocity == FixVector3.zero) { return(null); } var direction = (FixVector3)viewComponent.Transforms[0].forward; var offset = (FixVector3)capsuleCollider.center + bulletComponent.radius * direction; var origin = (FixVector3)viewComponent.Transforms[0].position + offset; var maxDistance = bulletComponent.velocity.magnitude * data.DeltaTime; RaycastHit hit; if (Physics.Raycast((Vector3)origin, (Vector3)direction, out hit, (float)maxDistance)) { viewComponent.Transforms[0].position = (Vector3)(origin + hit.distance * direction - offset); // Here we cannot directly use hit.normal as the direction, // because our collider may be simplified and does not match the model, // our scaling on the y-axis is relatively large to ensure that the decal can be printed on the model. EasyDecal.ProjectAt(GetMaterial(hit.collider.name).BulletHole, null, hit.point, viewComponent.Transforms[0].forward, 0, new Vector3(bulletComponent.holeSize, GetMaterial(hit.collider.name).DetectionDepth, bulletComponent.holeSize)); StartCoroutine(AsyncImpectEffect(hit.collider.name, hit.point, Quaternion.identity)); bulletComponent.velocity = FixVector3.zero; PoolFactory.Despawn(data.Entity); } else { viewComponent.Transforms[0].position = (Vector3)(origin + maxDistance * direction - offset); } return(null); }).AddTo(this.Disposer); }
public override void OnEnable() { base.OnEnable(); NetwrokTimeline.OnForward(data => { if (NetworkSystem.Mode != SessionMode.Offline && data.TickId % Interval == 0) { string msg = PackMessage(); analyzedDataDict.Add(data.TickId, msg); NetworkSystem.Publish(RequestCode.LockstepAnalysis, data.TickId.ToString() + VerticalBar + msg); } return(null); }).AddTo(this.Disposer); NetworkSystem.Receive(RequestCode.LockstepAnalysis).Subscribe(data => { int tickId; int returnCode; string[] strs = data.StringValue.Split(VerticalBar); if (strs.Length == 2 && int.TryParse(strs[0], out tickId)) { if (analyzedDataDict.ContainsKey(tickId)) { if (analyzedDataDict[tickId] == strs[1]) { Debug.Log(string.Format(DataMatchSuccess, tickId, analyzedDataDict[tickId], strs[1])); } else { Debug.LogError(string.Format(DataMatchFailed, tickId, analyzedDataDict[tickId], strs[1])); } } else { Debug.LogWarning(InsufficientDataWarning); } } else if (int.TryParse(data.StringValue, out returnCode) && (ReturnCode)returnCode == ReturnCode.Success) { } else { Debug.LogError(DataError); } }).AddTo(this.Disposer); }
public override void OnEnable() { base.OnEnable(); NetwrokTimeline.OnForward(data => { for (int i = 0; i < data.UserInputData[0].Length; i++) { for (int j = 0; j < data.UserInputData[0][i].Inputs.Length; j++) { var userId = data.UserInputData[0][i].UserId; var eventInput = data.UserInputData[0][i].GetInput <EventInput>(j); if (eventInput.Type == EventCode.GameStart) { var isRoomOwner = eventInput.Get <bool>(0); if (!HasUser(userId)) { var pos = isRoomOwner ? NetworkPlayerPrefab.transform.position + new Vector3(2, 0, -5) : NetworkPlayerPrefab.transform.position += new Vector3(-2, 0, -5); var rot = isRoomOwner ? Quaternion.Euler(0, -90, 0) : Quaternion.Euler(0, 90, 0); NetworkPrefabFactory.Instantiate(userId, data.TickId, NetworkPlayerPrefab, pos, rot); } } } } return(null); }).AddTo(this.Disposer); NetworkPlayerComponents.OnAdd().Subscribe(entity => { if (NetworkPlayerComponents.Entities.Count == UserComponents.Entities.Count) { var evt = new TriggerEnterEvent(); evt.Source = GameStartId; EventSystem.Send(evt); } }).AddTo(this.Disposer); }
public override void OnEnable() { base.OnEnable(); ShootComponents.OnAdd().Subscribe(entity => { var networkIdentityComponent = entity.GetComponent <NetworkIdentityComponent>(); var shootComponent = entity.GetComponent <ShootComponent>(); shootComponent.WeaponIndex.DistinctUntilChanged().Subscribe(index => { if (index >= 0 && index < shootComponent.Weapons.Count) { var name = shootComponent.Weapons[index]; var path = WeaponDAO.GetPath(name); var prefab = Resources.Load <GameObject>(path); var bullet = WeaponDAO.GetBullet(name); if (shootComponent.CurrentWeaponEntity != null) { PoolFactory.Despawn(shootComponent.CurrentWeaponEntity); } shootComponent.CurrentWeaponEntity = PoolFactory.Spawn(prefab, shootComponent.Parent); shootComponent.bulletPrefab = Resources.Load <GameObject>(BulletDAO.GetPath(bullet)); shootComponent.muzzleFlashesPrefab = Resources.Load <GameObject>(WeaponDAO.GetMuzzleFlashesEffectPath(name)); shootComponent.adsPosition = WeaponDAO.GetADSPosition(name); shootComponent.bulletLocalPosition = WeaponDAO.GetBulletSpawnPosition(name); shootComponent.muzzleFlashesPosition = WeaponDAO.GetMuzzleFlashesPosition(name); shootComponent.holeSize = BulletDAO.GetHoleSize(bullet); shootComponent.speed = WeaponDAO.GetSpeed(name); shootComponent.cooldown = WeaponDAO.GetCooldown(name); if (shootComponent.CurrentWeaponEntity != null) { var weaponViewComponent = shootComponent.CurrentWeaponEntity.GetComponent <ViewComponent>(); weaponViewComponent.Transforms[0].localPosition = WeaponDAO.GetPosition(name); shootComponent.weaponLocalRotation = Quaternion.Euler(new Vector3(0, 90, 90)); weaponViewComponent.Transforms[0].localRotation = shootComponent.weaponLocalRotation; } } else { shootComponent.WeaponIndex.Value = Mathf.Clamp(index, 0, shootComponent.Weapons.Count); } }).AddTo(this.Disposer).AddTo(shootComponent.Disposer); for (int i = 0; i < shootComponent.Weapons.Count; i++) { var path = BulletDAO.GetPath(WeaponDAO.GetBullet(shootComponent.Weapons[i])); var prefab = Resources.Load <GameObject>(path); for (int j = 0; j < WarmupBullets; j++) { PoolFactory.Despawn(PoolFactory.Spawn(prefab, networkIdentityComponent.Identity.UserId, 0)); } } }).AddTo(this.Disposer); NetwrokTimeline.OnForward(data => { var networkIdentityComponent = data.Entity.GetComponent <NetworkIdentityComponent>(); var playerControlComponent = data.Entity.GetComponent <PlayerControlComponent>(); var shootComponent = data.Entity.GetComponent <ShootComponent>(); var animator = data.Entity.GetComponent <Animator>(); var weaponViewComponent = shootComponent.CurrentWeaponEntity != null ? shootComponent.CurrentWeaponEntity.GetComponent <ViewComponent>() : null; var userInputData = data.UserInputData[0]; var mouseInput = userInputData[0].GetInput <MouseInput>(); var keyInput = userInputData[1].GetInput <KeyInput>(); var eventInputs = userInputData[2].GetInputs <EventInput>(); EventInput eventInput = null; for (int i = 0; i < eventInputs.Length; i++) { if (eventInputs[i].Type == EventCode.PlayerCamera) { eventInput = eventInputs[i]; break; } } if (mouseInput != null && keyInput != null) { if (playerControlComponent.Aim.Value == AimMode.Free && keyInput.KeyCodes.Contains((int)KeyCode.LeftAlt)) { } else if (weaponViewComponent != null && eventInput != null) { // The point hit by the muzzle is different from the point hit in the center of the screen. // So how to solve this problem, my solution is like this: // First, get the hit point in the center of the screen. // 0 - camera position, 1 - camera dirstion, 2 - camera far clip plane. RaycastHit hit; var ray = new Ray((Vector3)eventInput.Get <FixVector3>(0), (Vector3)eventInput.Get <FixVector3>(1)); var point = Physics.Raycast(ray, out hit, (float)eventInput.Get <Fix64>(2)) ? hit.point : ray.origin + (float)eventInput.Get <Fix64>(2) * ray.direction; // Reset rotation to default rotation weaponViewComponent.Transforms[0].localRotation = shootComponent.weaponLocalRotation; // If not in aim down sight mode, then I can fine-tune the angle of the gun to make the direction of // the bullet closer to the point at the center of the screen if (playerControlComponent.Aim.Value != AimMode.AimDownSight) { var targetDirection = (point - weaponViewComponent.Transforms[0].TransformPoint(shootComponent.bulletLocalPosition)).normalized; var angle = Vector3.Angle(weaponViewComponent.Transforms[0].forward, targetDirection); var t = angle == 0 ? 1 : Mathf.Clamp01(shootComponent.LimitAngle / angle); var rotation = Quaternion.LookRotation(Vector3.Lerp(weaponViewComponent.Transforms[0].forward, targetDirection, t)); weaponViewComponent.Transforms[0].rotation = rotation; } } animator.SetBool(Shoot_b, mouseInput.MouseButtons.Contains(0)); if (mouseInput.MouseButtons.Contains(0) && shootComponent.cooldownTime <= 0) { var entity = PoolFactory.Spawn(shootComponent.bulletPrefab, networkIdentityComponent.Identity.UserId, data.TickId); var bulletComponent = entity.GetComponent <BulletComponent>(); var bulletViewComponent = entity.GetComponent <ViewComponent>(); if (weaponViewComponent != null) { bulletViewComponent.Transforms[0].position = weaponViewComponent.Transforms[0].TransformPoint(shootComponent.bulletLocalPosition); bulletViewComponent.Transforms[0].rotation = Quaternion.LookRotation(weaponViewComponent.Transforms[0].forward, weaponViewComponent.Transforms[0].up); bulletComponent.velocity = shootComponent.speed * (FixVector3)bulletViewComponent.Transforms[0].forward; bulletComponent.holeSize = shootComponent.holeSize; StartCoroutine(AsyncMuzzleFlashes(shootComponent.muzzleFlashesPrefab, weaponViewComponent.Transforms[0].TransformPoint(shootComponent.muzzleFlashesPosition), weaponViewComponent.Transforms[0].rotation)); } shootComponent.cooldownTime = shootComponent.cooldown; } } shootComponent.cooldownTime -= data.DeltaTime; return(null); }).AddTo(this.Disposer); }
public override void OnEnable() { base.OnEnable(); Network.OnUpdate += UpdateInputs; NetwrokTimeline.OnForward((entity, userInputData, deltaTime) => { var isLocalPlayer = !entity.HasComponent <NetworkIdentityComponent>() || entity.GetComponent <NetworkIdentityComponent>().IsLocalPlayer; if (isLocalPlayer && ThridPersonCameraComponents.Entities.Count > 0) { var playerControlComponent = entity.GetComponent <PlayerControlComponent>(); var shootComponent = entity.GetComponent <ShootComponent>(); var thridPersonCameraComponent = ThridPersonCameraComponents.Entities[0].GetComponent <ThridPersonCameraComponent>(); var virtualCamera = ThridPersonCameraComponents.Entities[0].GetComponent <CinemachineVirtualCamera>(); var collider = ThridPersonCameraComponents.Entities[0].GetComponent <CinemachineCollider>(); var transposer = virtualCamera.GetCinemachineComponent(CinemachineCore.Stage.Body) as CinemachineTransposer; virtualCamera.Follow = playerControlComponent.Follow; virtualCamera.LookAt = playerControlComponent.LookAt; if (playerControlComponent.Aim.Value == AimMode.Free) { thridPersonCameraComponent.smoothTime = Mathf.Clamp01(thridPersonCameraComponent.smoothTime - thridPersonCameraComponent.Smooth * (float)deltaTime); } else if (playerControlComponent.Aim.Value == AimMode.Shoulder) { thridPersonCameraComponent.smoothTime = Mathf.Clamp01(thridPersonCameraComponent.smoothTime + thridPersonCameraComponent.Smooth * (float)deltaTime); } if (playerControlComponent.Aim.Value == AimMode.AimDownSight) { if (shootComponent.CurrentWeaponEntity != null) { var viewComponent = shootComponent.CurrentWeaponEntity.GetComponent <ViewComponent>(); transposer.m_FollowOffset = virtualCamera.Follow.InverseTransformDirection(viewComponent.Transforms[0].position - virtualCamera.Follow.position) + shootComponent.adsPosition; } } else { transposer.m_FollowOffset = Vector3.Lerp(thridPersonCameraComponent.FollowOffset[(int)AimMode.Free], thridPersonCameraComponent.FollowOffset[(int)AimMode.Shoulder], thridPersonCameraComponent.smoothTime); } if (CrosshairComponents.Entities.Count > 0) { var crosshairComponent = CrosshairComponents.Entities[0].GetComponent <CrosshairComponent>(); var viewComponent = CrosshairComponents.Entities[0].GetComponent <ViewComponent>(); var rectTransform = viewComponent.Transforms[0] as RectTransform; if (playerControlComponent.Aim.Value == AimMode.AimDownSight) { rectTransform.sizeDelta = Vector2.zero; } else { rectTransform.sizeDelta = Mathf.Lerp(crosshairComponent.Free, crosshairComponent.Shoulder, thridPersonCameraComponent.smoothTime) * Vector2.one; } } collider.m_DistanceLimit = transposer.m_FollowOffset.magnitude; } return(null); }).AddTo(this.Disposer); }
public override void OnEnable() { base.OnEnable(); PlayerControlComponents.OnAdd() .Where(entity => !entity.HasComponent <NetworkPlayerComponent>()) .Subscribe(entity => { var playerControlComponent = entity.GetComponent <PlayerControlComponent>(); var characterController = entity.GetComponent <CharacterController>(); var viewComponent = entity.GetComponent <ViewComponent>(); Observable.EveryUpdate().Subscribe(_ => { if (characterController.isGrounded) { var angle = Vector3.Angle(viewComponent.Transforms[0].forward, mainCamera.transform.forward); if (angle < InvertRange.Min || angle > InvertRange.Max) { playerControlComponent.motion = new FixVector3(Input.GetAxis(InputParameters.Horizontal), 0, Input.GetAxis(InputParameters.Vertical)); } else { playerControlComponent.motion = new FixVector3(Input.GetAxis(InputParameters.Vertical), 0, Input.GetAxis(InputParameters.Horizontal)); } playerControlComponent.motion = (FixVector3)viewComponent.Transforms[0].TransformDirection((Vector3)playerControlComponent.motion); playerControlComponent.motion *= playerControlComponent.Run; if (Input.GetButton(InputParameters.Jump)) { playerControlComponent.motion.y = playerControlComponent.Jump; } } playerControlComponent.motion.y -= playerControlComponent.Gravity * Time.deltaTime; characterController.Move((Vector3)playerControlComponent.motion * Time.deltaTime); }).AddTo(this.Disposer).AddTo(playerControlComponent.Disposer); }).AddTo(this.Disposer); NetwrokTimeline.OnReverse((entity, result) => { var playerControlComponent = entity.GetComponent <PlayerControlComponent>(); var viewComponent = entity.GetComponent <ViewComponent>(); var playerControlResult = (PlayerControlResult)result[0]; viewComponent.Transforms[0].rotation = playerControlResult.Rotation; playerControlComponent.Follow.rotation = playerControlResult.Follow; viewComponent.Transforms[0].position = playerControlResult.Position; }).AddTo(this.Disposer); NetwrokTimeline.OnForward((entity, userInputData, deltaTime) => { var playerControlComponent = entity.GetComponent <PlayerControlComponent>(); var characterController = entity.GetComponent <CharacterController>(); var viewComponent = entity.GetComponent <ViewComponent>(); var animator = entity.GetComponent <Animator>(); var axisInput = userInputData[0].GetInput <AxisInput>(); var keyInput = userInputData[1].GetInput <KeyInput>(); var mouseInput = userInputData[2].GetInput <MouseInput>(); var playerControlResult = new PlayerControlResult(); var smoothTime = playerControlComponent.smoothTime; var yAngle = Fix64.Zero; playerControlResult.Rotation = viewComponent.Transforms[0].rotation; playerControlResult.Follow = playerControlComponent.Follow.rotation; playerControlResult.Position = viewComponent.Transforms[0].position; if (mouseInput != null && keyInput != null && axisInput != null) { var rotLeftRight = mouseInput.Delta.x * playerControlComponent.MouseSensivity.x * deltaTime; var rotUpDown = mouseInput.Delta.y * playerControlComponent.MouseSensivity.y * deltaTime; if (mouseInput.MouseButtons.Contains(1)) { playerControlComponent.aimTime += deltaTime; if (playerControlComponent.Aim.Value == AimMode.Free && playerControlComponent.aimTime > ShoulderAimTime) { playerControlComponent.Aim.Value = AimMode.Shoulder; } } else { if (playerControlComponent.Aim.Value == AimMode.Free) { if (playerControlComponent.aimTime > 0) { playerControlComponent.Aim.Value = AimMode.AimDownSight; } } else if (playerControlComponent.aimTime > 0) { playerControlComponent.Aim.Value = AimMode.Free; } playerControlComponent.aimTime = 0; } if (playerControlComponent.Aim.Value == AimMode.Free && keyInput.KeyCodes.Contains((int)KeyCode.LeftAlt)) { playerControlComponent.Follow.rotation = (Quaternion)((FixQuaternion)playerControlComponent.Follow.rotation * FixQuaternion.Euler(-rotUpDown, rotLeftRight, 0)); animator.SetFloat(Head_Vertical_f, 0); animator.SetFloat(Body_Vertical_f, 0); smoothTime = SmoothTime; } else { if (smoothTime > 0) { playerControlComponent.Follow.localRotation = (Quaternion)FixQuaternion.Lerp(FixQuaternion.identity, (FixQuaternion)playerControlComponent.Follow.localRotation, FixMath.Clamp01(smoothTime / SmoothTime)); animator.SetFloat(Head_Vertical_f, 0); animator.SetFloat(Body_Vertical_f, 0); smoothTime -= deltaTime; } else { yAngle = ClampAngle(playerControlComponent.Follow.localEulerAngles.x, playerControlComponent.YAngleLimit.Min, playerControlComponent.YAngleLimit.Max); yAngle = ClampAngle(yAngle - rotUpDown, playerControlComponent.YAngleLimit.Min, playerControlComponent.YAngleLimit.Max); var vertical = 2 * (0.5f - FixMath.Abs(yAngle - playerControlComponent.YAngleLimit.Min) / FixMath.Abs(playerControlComponent.YAngleLimit.Max - playerControlComponent.YAngleLimit.Min)); animator.SetFloat(Head_Vertical_f, 0.5f * (float)vertical); animator.SetFloat(Body_Vertical_f, (float)vertical); viewComponent.Transforms[0].rotation = (Quaternion)((FixQuaternion)viewComponent.Transforms[0].rotation * FixQuaternion.Euler(0, rotLeftRight, 0)); playerControlComponent.Follow.localEulerAngles = (Vector3) new FixVector3(yAngle, 0, 0); } } if (characterController.isGrounded) { playerControlComponent.motion = new FixVector3((float)axisInput.Horizontal, 0, (float)axisInput.Vertical); playerControlComponent.motion = (FixVector3)viewComponent.Transforms[0].TransformDirection((Vector3)playerControlComponent.motion); Fix64 t = 0.75f; Fix64 speed = playerControlComponent.Walk; Fix64 h = FixMath.Abs(axisInput.Horizontal); Fix64 sum = h + FixMath.Abs(axisInput.Vertical); Fix64 horizontal = sum == 0 ? 0 : axisInput.Horizontal * (h / sum); if (playerControlComponent.Aim.Value == AimMode.Shoulder) { t = 0.5f; } else if (playerControlComponent.Aim.Value == AimMode.AimDownSight) { t = 0.25f; } else if (keyInput != null && keyInput.KeyCodes.Contains((int)KeyCode.LeftShift)) { t = 1f; speed = playerControlComponent.Run; } playerControlComponent.Crouched = keyInput.KeyCodes.Contains((int)KeyCode.LeftControl); animator.SetBool(Crouch_b, playerControlComponent.Crouched); if (playerControlComponent.Crouched) { speed = 0; } playerControlComponent.motion *= t * speed; animator.SetFloat(Speed_f, (axisInput.Horizontal != Fix64.Zero || axisInput.Vertical != Fix64.Zero) ? (float)FixMath.Clamp(t, 0.3f, 1f) : 0f); animator.SetFloat(Head_Horizontal_f, 0.25f * (float)horizontal); animator.SetFloat(Body_Horizontal_f, 0.35f * (float)horizontal); } if (keyInput.KeyCodes.Contains((int)KeyCode.Space) && !playerControlComponent.Crouched) { playerControlComponent.motion.y = playerControlComponent.Jump; } } playerControlComponent.motion.y -= playerControlComponent.Gravity * deltaTime; playerControlComponent.smoothTime = smoothTime; characterController.Move((Vector3)(playerControlComponent.motion * deltaTime)); animator.SetBool(Jump_b, playerControlComponent.motion.y > 0); animator.SetBool(Grounded, characterController.isGrounded && playerControlComponent.motion.y <= 0); return(new IUserInputResult[] { playerControlResult }); }).AddTo(this.Disposer); }