private void OnFadedOut(EasyDecal decal) { decal.transform.SetParent(null); decal.OnFadedOut -= OnFadedOut; PoolFactory.Despawn(decalDict[decal]); decalDict.Remove(decal); }
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(); blockSetupers.OnAdd().Subscribe(entity => { var viewComponent = entity.GetComponent <ViewComponent>(); var blockSetuper = entity.GetComponent <BlockSetuper>(); var counter = new List <Dictionary <GameObject, int> >(); var prefabs = new List <GameObject>(); var blocks = new List <GameObject>(); var maximum = new Dictionary <GameObject, int>(); var disposer = new CompositeDisposable(); foreach (var block in blockSetuper.Setup.Blocks) { var subCounter = new Dictionary <GameObject, int>(); foreach (var kvp in block.ToDictionary()) { if (!subCounter.ContainsKey(kvp.Value.GameObject)) { subCounter.Add(kvp.Value.GameObject, 1); } else { subCounter[kvp.Value.GameObject]++; } if (!prefabs.Contains(kvp.Value.GameObject)) { prefabs.Add(kvp.Value.GameObject); } } counter.Add(subCounter); } foreach (var prefab in prefabs) { var max = 0; foreach (var c in counter) { if (c.ContainsKey(prefab) && c[prefab] > max) { max = c[prefab]; } } maximum.Add(prefab, max); } viewComponent.Transforms[0].OnActiveAsObservable().Subscribe(_ => { foreach (var prefab in prefabs) { for (int i = 0; i < blockSetuper.MaxVisibleCount * maximum[prefab]; i++) { PoolFactory.Despawn(PoolFactory.Spawn(prefab, transform)); } } int index = 0; blocks.Add(CreateBlock(blockSetuper.Setup.Blocks[index], viewComponent.Transforms[0])); EventSystem.OnEvent <RequestBlockProcessingEvent>().Subscribe(evt => { index++; if (index < blockSetuper.Setup.Blocks.Count) { var block = CreateBlock(blockSetuper.Setup.Blocks[index], viewComponent.Transforms[0]); block.transform.position = new Vector3(0, 0, 50 * index); blocks.Add(block); } while (blocks.Count > blockSetuper.MaxVisibleCount) { RemoveBlock(blocks[0]); blocks.RemoveAt(0); } }).AddTo(this.Disposer).AddTo(blockSetuper.Disposer).AddTo(disposer); }).AddTo(this.Disposer).AddTo(blockSetuper.Disposer); viewComponent.Transforms[0].OnInactiveAsObservable().Subscribe(_ => { disposer.Clear(); foreach (var block in blocks) { RemoveBlock(block); } }).AddTo(this.Disposer).AddTo(blockSetuper.Disposer); }).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); }