I've got a ship that's spawning sprites. There are two types: railgun rounds and missiles. The missiles fire off properly, but the railgun rounds always spawn about one hundred pixels in front of the ship (or at least, it seems to). I'm not sure why this is happening. Also, there are two turrets, when it fires out of one, it's supposed to set a boolean value to true to make it fire out of the other one; when it fires out of that one, it sets the boolean back to false and so on. It always fires out of the first one. Again, no idea why. I've been banging my head against this all day. Here's my code:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using ShipBattle.Classes.Ships;
using ShipBattle.Classes.Ships.Fighters;
using ShipBattle.Classes.Ships.Projectiles;
using ShipBattle.Classes.Ships.Projectiles.Tauri;
namespace ShipBattle.Classes.Ships.Fighters
{
public class F302 : Ship
{
const double missileMinimumFiringArc = Utilities.NINETY_DEGREES / 2;
const double missileMaximumFiringArc = Utilities.NINETY_DEGREES + (Utilities.NINETY_DEGREES / 2);
const double railgunMinimumFiringArc = 1.5;
const double railgunMaximumFiringArc = 1.6;
const double MISSILES_ROF = 30.0;
protected List<double> CooldownLeft = new List<double>();
private ContentManager content;
public event ShipFired WeaponFired;
public List<NaquadahEnhancedMissile> missiles;
public List<RailgunRound> railgunRounds;
public int[] MissileAmmo { get; set; }
public int[] RailgunAmmo { get; set; }
//Determines which missile/railgun to fire
bool leftMissile = true;
bool leftRailgun = true;
public F302(Vector2 position, ContentManager Content)
{
content = Content;
Texture = content.Load<Texture2D>(#"Textures\Ships\Tauri\Fighters\F302");
Position = position;
Rotation = 0;
#region Physics Stuff
mass = 19200;
force = 76.3f;
acceleration = (force * 1000) / mass;
maxSpeed = Utilities.GetVelocity(acceleration);
#endregion
#region Hull & Shielding
HullIntegrity = 10;
ShieldStrength = 0;
#endregion
#region Weapons!!!
/*
* [0] = Port Missile
* [1] = Starboard Missile
* [2] = Port Railgun
* [3] = Starboard Railgun
*/
//Setup
missiles = new List<NaquadahEnhancedMissile>();
railgunRounds = new List<RailgunRound>();
MissileAmmo = new int[2];
RailgunAmmo = new int[2];
//Port Missile
WeaponRatesOfFire.Add(MISSILES_ROF);
CooldownLeft.Add(0);
WeaponsEnplacements.Add(new Vector2(14, 5));
WeaponEmplacementOffsets.Add(new Vector2(14, 5));
MissileAmmo[0] = 2;
//Starboard Missile
WeaponRatesOfFire.Add(MISSILES_ROF);
CooldownLeft.Add(0);
WeaponsEnplacements.Add(new Vector2(35, 5));
WeaponEmplacementOffsets.Add(new Vector2(35, 5));
MissileAmmo[1] = 2;
//Port Railgun
WeaponRatesOfFire.Add(7.2);
CooldownLeft.Add(0);
WeaponsEnplacements.Add(new Vector2(24, 0));
WeaponEmplacementOffsets.Add(new Vector2(24, 0));
RailgunAmmo[0] = 10000;
//Starboard Railgun
WeaponRatesOfFire.Add(7.2);
CooldownLeft.Add(0);
WeaponsEnplacements.Add(new Vector2(26, 0));
WeaponEmplacementOffsets.Add(new Vector2(26, 0));
RailgunAmmo[1] = 10000;
#endregion
}
protected override void UpdateProjectiles(Vector2 pos)
{
for (int i = 0; i < missiles.Count; i++)
if (missiles[i].Remove)
missiles.RemoveAt(i);
for (int i = 0; i < railgunRounds.Count; i++)
if (railgunRounds[i].Remove)
railgunRounds.RemoveAt(i);
foreach (NaquadahEnhancedMissile nem in missiles)
nem.Update(enemyPos);
foreach (RailgunRound rr in railgunRounds)
rr.Update(enemyPos);
}
protected override void DrawProjectiles(SpriteBatch spriteBatch)
{
foreach (NaquadahEnhancedMissile nem in missiles)
nem.Draw(spriteBatch);
foreach (RailgunRound rr in railgunRounds)
rr.Draw(spriteBatch);
}
protected override void CheckTarget(Ship target)
{
enemyPos = target.Position;
double distance = Vector2.Distance(Position, target.Position);
Vector2 vector1 = Vector2.Normalize(Position - target.Position);
Vector2 vector2 = new Vector2((float)Math.Cos(Rotation), (float)Math.Sin(Rotation));
double angle = Math.Acos(Vector2.Dot(vector1, vector2));
if (angle > missileMinimumFiringArc && angle < missileMaximumFiringArc)
if (distance < 500)
if (((target.HullIntegrity + target.ShieldStrength) - 10) <= 0)
FireMissiles();
if (angle > railgunMinimumFiringArc && angle < railgunMaximumFiringArc)
FireRailguns();
}
protected void FireMissiles()
{
if (leftMissile)
{
if (CooldownLeft[0] <= 0)
{
if (MissileAmmo[0] > 0)
{
NaquadahEnhancedMissile nem = new NaquadahEnhancedMissile(WeaponsEnplacements[0], Rotation, content);
nem.hit += new ProjectileHit(nem_hit);
missiles.Add(nem);
CooldownLeft[0] = WeaponRatesOfFire[0];
CooldownLeft[1] = WeaponRatesOfFire[1];
MissileAmmo[0]--;
leftMissile = false;
}
}
}
else
if (CooldownLeft[1] <= 0)
{
if (MissileAmmo[1] > 0)
{
NaquadahEnhancedMissile nem = new NaquadahEnhancedMissile(WeaponsEnplacements[1], Rotation, content);
nem.hit += new ProjectileHit(nem_hit);
missiles.Add(nem);
CooldownLeft[0] = WeaponRatesOfFire[0];
CooldownLeft[1] = WeaponRatesOfFire[1];
MissileAmmo[1]--;
leftMissile = true;
}
}
}
private void FireRailguns()
{
if (leftRailgun)
{
if (CooldownLeft[2] <= 0)
{
if (RailgunAmmo[0] > 0)
{
RailgunRound rgr = new RailgunRound(WeaponsEnplacements[2], Rotation, content);
rgr.hit += new ProjectileHit(nem_hit);
railgunRounds.Add(rgr);
CooldownLeft[2] = WeaponRatesOfFire[2];
CooldownLeft[3] = WeaponRatesOfFire[3];
RailgunAmmo[0]--;
leftRailgun = false;
}
}
}
else
if (CooldownLeft[3] <= 0)
{
if (RailgunAmmo[1] > 0)
{
RailgunRound rgr = new RailgunRound(WeaponsEnplacements[3], Rotation, content);
rgr.hit += new ProjectileHit(nem_hit);
railgunRounds.Add(rgr);
CooldownLeft[2] = WeaponRatesOfFire[2];
CooldownLeft[3] = WeaponRatesOfFire[3];
MissileAmmo[1]--;
leftRailgun = true;
}
}
}
protected override void Cooldown()
{
for (int f = 0; f < CooldownLeft.Count; f++)
CooldownLeft[f]--;
}
private void nem_hit(Projectile p, EventArgs e)
{
if (p is NaquadahEnhancedMissile)
{
p.Remove = true;
if (targetShip.ShieldStrength > 0)
targetShip.ShieldStrength -= p.Damage;
else
targetShip.HullIntegrity -= p.Damage;
}
else if (p is RailgunRound)
{
p.Remove = true;
if (targetShip.ShieldStrength > 0)
targetShip.ShieldStrength -= p.Damage / 4;
else
targetShip.HullIntegrity -= p.Damage;
}
}
protected override void CleanupProjectiles()
{
missiles.Clear();
railgunRounds.Clear();
}
}
}
And here's the code for the ship class this all inherits from:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using ShipBattle.Classes.Ships.Projectiles;
using ShipBattle.Classes.Ships.Projectiles.Tauri;
namespace ShipBattle.Classes.Ships
{
public abstract class Ship
{
public Texture2D Texture { get; set; }
public Vector2 Position
{
get
{
return _position;
}
set
{
_position = value;
}
}
public float Rotation { get; set; }
private Vector2 _position;
protected Ship targetShip;
protected Vector2 enemyPos;
#region Health & Shielding
public float HullIntegrity { get; set; }
public float ShieldStrength { get; set; }
public bool Remove { get; set; }
#endregion
#region Guns
protected List<Vector2> WeaponsEnplacements = new List<Vector2>();
protected List<Vector2> WeaponEmplacementOffsets = new List<Vector2>();
protected List<double> WeaponRatesOfFire = new List<double>();
/// <summary>
/// The rates of fire for all weapons, represented in terms of the delay between frames
/// </summary>
#endregion
#region Targeting Logic
bool hasTarget = false;
protected int targetHashCode;
Vector2 targetShipPosition;
Ship target;
bool evasive = false;
bool hasRandomTrajectory = false;
bool reachedBounds = false;
bool followingRandom = false;
int timeToFaffAbout = 360;
double randomRotation;
#endregion
#region Physics Stuff
float angleA, b, a, speed = 0;
double turningRadius = 10 * (Math.PI / 180);
//Acceleration
protected int mass; // kg
protected float force; // kN, thruster power
protected float acceleration; // m/s^2
//Velocity
protected float maxSpeed; // m/s, calculated using 30-second burn
protected float initialSpeed = 0;
protected float finalSpeed = 0;
protected float time = 0.016666f;
#endregion
public void Update(List<Ship> ships)
{
if (timeToFaffAbout >= 0)
{
timeToFaffAbout = 360;
followingRandom = false;
}
if (!hasTarget)
{
targetShip = GetTarget(ships);
hasTarget = true;
}
else
{
if (targetShip != null)
{
if (Vector2.Distance(Position, targetShip.Position) < 75)
evasive = true;
else
evasive = false;
if (evasive)
{
if (!hasRandomTrajectory)
{
Random random = new Random();
randomRotation = random.Next((int)(Math.PI * 100));
double negative = random.Next(2);
if (negative == 1)
randomRotation *= -1;
Rotation = (float)randomRotation;
hasRandomTrajectory = true;
}
}
else
{
if (!followingRandom)
{
//Rotate the sprite using the turning radius
Rotation = Utilities.TurnToFace(Position, new Vector2(targetShip.Position.X, targetShip.Position.Y), (float)Rotation, (float)turningRadius);
}
}
KeepOnTheScreen();
//Move the sprite, using KINEMATIC PHYSICS, ***!!! -->goes in the direction set by the rotation algorithm
Move();
CheckTarget(targetShip);
UpdateProjectiles(targetShip.Position);
//Stop targeting a dead enemy
if (targetShip.HullIntegrity <= 0)
hasTarget = false;
}
}
//Recalculate the List<Vector2> weapons enplacements based on the current rotation angle
RecalculateWeaponsPositions();
//Cooldown the guns
Cooldown();
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(Texture, Position, null, Color.White, Rotation, new Vector2(Texture.Width / 2, Texture.Height / 2), 0.5f,
SpriteEffects.None, 0.0f);
if (hasTarget)
DrawProjectiles(spriteBatch);
}
/// <summary>
/// Uses trig and the thruster power to move the ship. b is the y distance to move, a is the x distance to move
/// </summary>
private void Move()
{
if (finalSpeed < maxSpeed)
finalSpeed = speed + (acceleration * time);
angleA = Rotation;
b = (float)Math.Cos(angleA) * finalSpeed;
a = (float)Math.Sin(angleA) * finalSpeed;
_position.Y -= b;
_position.X += a;
speed = finalSpeed;
}
/// <summary>
/// Acquires the closes enemy ship
/// </summary>
/// <param name="ships">The ships to search through</param>
/// <returns></returns>
private Ship GetTarget(List<Ship> ships)
{
CleanupProjectiles();
Ship rVal = null;
int distance = int.MaxValue;
float c;
foreach (Ship ship in ships)
{
c = Vector2.Distance(Position, ship.Position);
if (c < distance)
rVal = ship;
}
return rVal;
}
/// <summary>
/// Reorients the positions of all the weapon positions on this ship
/// </summary>
private void RecalculateWeaponsPositions()
{
for (int i = 0; i < WeaponsEnplacements.Count; i++)
{
WeaponsEnplacements[i] = RotateWeapons(WeaponEmplacementOffsets[i]);
}
}
/// <summary>
/// Recalculates the positions of the weapons on this ship based off their default offset and the current angle
/// </summary>
/// <param name="weapon">The weapon position to recalculate</param>
/// <param name="offset">The default offset of that weapon</param>
private Vector2 RotateWeapons(Vector2 offset)
{
Quaternion rotation = Quaternion.CreateFromAxisAngle(Vector3.Backward, (float)Rotation);
return Vector2.Transform(offset, rotation) + Position;
}
/// <summary>
/// Keeps the ship on the screen
/// </summary>
private void KeepOnTheScreen()
{
if (Position.X > 1019 || Position.X < 5 || Position.Y > 761 || Position.Y < 5)
reachedBounds = true;
else
reachedBounds = false;
if (reachedBounds)
{
followingRandom = true;
if (!followingRandom)
Rotation = Utilities.TurnToFace(Position, new Vector2(1024 / 2, 768 / 2), Rotation, (float)turningRadius);
else
timeToFaffAbout--;
}
}
/// <summary>
/// Checks to see if the target ship is within weapons range
/// </summary>
/// <param name="target"></param>
protected abstract void CheckTarget(Ship target);
/// <summary>
/// Decrements the cooldown of all weapons
/// </summary>
protected abstract void Cooldown();
protected abstract void UpdateProjectiles(Vector2 pos);
protected abstract void DrawProjectiles(SpriteBatch spriteBatch);
protected abstract void CleanupProjectiles();
}
}
If anyone can help me with this, I'd be really appreciative. Thank you!
Why does FireRailguns() execute MissileAmmo[1]--; ?
Related
I've been attempting to rid myself of this NavMeshAgent error for about 2 weeks now but can't seem to overcome it so I'm turning to SO.
I have a Navigation Mesh, I have prodigally spawned enemies which are placed on the Navigation Mesh however I receive this error constantly to where my console is filled (999+) with this error. The error is:
"SetDestination" can only be called on an active agent that has been placed on a NavMesh.
UnityEngine.AI.NavMeshAgent:SetDestination(Vector3)
ZombieAI:Update() (at Assets/Scripts/ZombieAI.cs:137)
Any help on squashing this error would be greatly appreciated as it sucks all performance out of my program to a point of not being usable.
The script is as follows:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using FSG.MeshAnimator;
public class ZombieAI : MonoBehaviour
{
/// <summary>
/// Components
/// </summary>
MeshAnimator mesh;
AudioSource audioSrc;
SphereCollider sphereCollider;
CapsuleCollider capsuleCollider;
NavMeshAgent agent;
/// <summary>
/// Child Objects
/// </summary>
GameObject EnemyIcon;
/// <summary>
/// Animations
/// </summary>
public MeshAnimation[] deathAnimations = new MeshAnimation[5];
string curDeathAnimations;
public MeshAnimation[] runAnimations = new MeshAnimation[1];
/// <summary>
/// Sounds
/// </summary>
public AudioSource _as;
public AudioClip[] infectedNoises;
public int randomNoiseNum;
/// <summary>
/// Textures
/// </summary>
public Texture[] mantexture = new Texture[16];
public Texture[] womantexture = new Texture[17];
/// <summary>
/// Health
/// </summary>
public float max_health = 5f;
public float cur_health = 5f;
public float distance;
/// <summary>
/// Awareness
/// </summary>
public bool female;
public bool alive;
public bool spotted = false;
public bool attack = false;
bool create = false;
/// <summary>
/// Targets
/// </summary>
public GameObject target;
/// <summary>
/// Veriables
/// </summary>
public float velocity;
private Vector3 previous;
[Range(0f, 1.35f)]
public float attackRange;
[Range(3f, 5f)]
public float runAttackRange;
[Range(1f, 100f)]
public float detectionRange;
[Range(1f, 10f)]
public float runSpeed = 3.5f;
float onMeshThreshold = 3;
private void Start()
{
if (female == false)
{
gameObject.GetComponent<Renderer>().material.SetTexture("_MainTex", mantexture[Random.Range(0, mantexture.Length)]);
}
if (female == true)
{
GetComponent<Renderer>().material.SetTexture("_MainTex", womantexture[Random.Range(0, womantexture.Length)]);
}
curDeathAnimations = deathAnimations[Random.Range(0, deathAnimations.Length)].name;
//EnemyIcon = transform.Find("Enemy-Icon").gameObject;
mesh = GetComponent<MeshAnimator>();
audioSrc = GetComponent<AudioSource>();
_as = GetComponent<AudioSource>();
sphereCollider = GetComponent<SphereCollider>();
capsuleCollider = GetComponent<CapsuleCollider>();
agent = GetComponent<NavMeshAgent>();
target = GameObject.FindGameObjectWithTag("Player");
alive = true;
if (transform.position.y <= 0 && transform.position.y >= 1)
{
Destroy(gameObject);
}
}
public void Update()
{
if (alive)
{
distance = Vector3.Distance(target.transform.position, transform.position);
velocity = ((transform.position - previous).magnitude) / Time.deltaTime;
previous = transform.position;
if (transform.position.y <= 1 && transform.position.y >= -1)
{
create = true;
if (create == false)
{
Destroy(gameObject);
}
else if (create == true)
{
agent.SetDestination(target.transform.position);
}
}
if (velocity > 0 && !attack)
{
mesh.speed = velocity / 3;
mesh.Play("Run1-0");
}
if (velocity > 0 && attack && spotted)
{
spotted = true;
mesh.Play("Run Attack");
}
else if (velocity == 0 && attack && spotted)
{
mesh.Play("Attack1-0");
}
if (distance < detectionRange)
{
spotted = true;
}
if (spotted && distance < attackRange)
{
Vector3 targetPosition = new Vector3(target.transform.position.x, transform.position.y, target.transform.position.z);
transform.LookAt(targetPosition);
}
randomNoiseNum = Random.Range(0, 400);
if (alive && randomNoiseNum == 20)
{
PlayRandomNoise();
}
}
/* if (alive && distance > attackRange && velocity <= 0.05f && !attack)
{
mesh.Play("Idle1-0");
}*/
if (!alive)
{
//mesh.Play(curDeathAnimations);
//ScoreManager.scoreValue += 1;
Destroy(gameObject, 5);
}
if (cur_health <= 0)
{
mesh.speed = 1;
alive = !alive;
mesh.Play(curDeathAnimations);
//Destroy(mesh,0);
Destroy(EnemyIcon);
Destroy(audioSrc, 0);
Destroy(sphereCollider, 0);
Destroy(capsuleCollider, 0);
Destroy(agent, 0);
alive = false;
}
}
void OnTriggerStay(Collider col)
{
attack = true;
}
void OnTriggerExit(Collider col)
{
attack = false;
}
public void PlayRandomNoise()
{
if (female == true)
{
_as.volume = 2.0f;
_as.clip = infectedNoises[Random.Range(0, infectedNoises.Length)];
_as.pitch = Random.Range(1.10f, 1.35f);
_as.PlayOneShot(_as.clip);
}
else
{
_as.volume = 2.0f;
_as.pitch = Random.Range(0.75f, 1.05f);
_as.clip = infectedNoises[Random.Range(0, infectedNoises.Length)];
_as.PlayOneShot(_as.clip);
}
}
}
I am having a problem with my RTS game where my enemy units will not attack any base buildings I create after the level starts. They go to attack every other building that was there when the level starts, but none of the built ones.
There is a list being set up of the closest targets to units and they will go to attack their closest target, but any newly instantiated buildings or units, don't get attacked for some reason.
The function DecideWhatToDo() is called on all units in the WorldObject script when they are not doing anything. It then calls FindNearbyObjects() from the WorkManager script.
Everything works up until new units and buildings are created, has anyone experienced this kind of problem before?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using RTS;
public class WorldObject : MonoBehaviour {
BoxCollider boxCollider;
bool isDead;
bool isSinking;
public string objectName;
public Texture2D buildImage;
public int cost, sellValue, maxHitPoints;
public float hitPoints;
public virtual bool IsActive { get { return true; } }
public float weaponRange = 10.0f;
public float weaponRechargeTime = 1.0f;
public float weaponAimSpeed = 1.0f;
public AudioClip attackSound, selectSound, useWeaponSound;
public float attackVolume = 1.0f, selectVolume = 1.0f, useWeaponVolume = 1.0f;
public int ObjectId { get; set; }
public float detectionRange = 20.0f;
public GameObject explosionPrefab, splat;
protected NavMeshAgent agent;
protected AudioElement audioElement;
protected Animator anim;
protected List<WorldObject> nearbyObjects;
protected Rect playingArea = new Rect(0.0f, 0.0f, 0.0f, 0.0f);
protected Player player;
protected string[] actions = { };
protected bool currentlySelected = false;
protected Bounds selectionBounds;
protected GUIStyle healthStyle = new GUIStyle();
protected float healthPercentage = 1.0f;
protected WorldObject target = null;
protected bool attacking = false;
protected bool movingIntoPosition = false;
protected bool aiming = false;
private List<Material> oldMaterials = new List<Material>();
private float currentWeaponChargeTime;
//we want to restrict how many decisions are made to help with game performance
//the default time at the moment is a tenth of a second
private float timeSinceLastDecision = 0.0f, timeBetweenDecisions = 0.1f;
protected virtual void Awake()
{
anim = GetComponent<Animator>();
boxCollider = GetComponent<BoxCollider>();
selectionBounds = ResourceManager.InvalidBounds;
CalculateBounds();
}
protected virtual void Start()
{
agent = GetComponent<NavMeshAgent>();
SetPlayer();
if (player) SetTeamColor();
InitialiseAudio();
}
protected virtual void Update()
{
if (isSinking)
{
this.transform.Translate(-Vector3.up * 2.5f * Time.deltaTime);
}
if (ShouldMakeDecision()) DecideWhatToDo();
currentWeaponChargeTime += Time.deltaTime;
if (attacking && !movingIntoPosition && !aiming)
{
PerformAttack();
}
}
/**
* A child class should only determine other conditions under which a decision should
* not be made. This could be 'harvesting' for a harvester, for example. Alternatively,
* an object that never has to make decisions could just return false.
*/
protected virtual bool ShouldMakeDecision()
{
if (!attacking && !movingIntoPosition && !aiming)
{
//we are not doing anything at the moment
if (timeSinceLastDecision > timeBetweenDecisions)
{
timeSinceLastDecision = 0.0f;
Debug.Log("");
return true;
}
timeSinceLastDecision += Time.deltaTime;
}
return false;
}
protected virtual void DecideWhatToDo()
{
//determine what should be done by the world object at the current point in time
Vector3 currentPosition = transform.position;
nearbyObjects = WorkManager.FindNearbyObjects(currentPosition, detectionRange);
if (CanAttack())
{
List<WorldObject> enemyObjects = new List<WorldObject>();
foreach (WorldObject nearbyObject in nearbyObjects)
{
Resource resource = nearbyObject.GetComponent<Resource>();
if (resource) continue;
if (nearbyObject.GetPlayer() != player) enemyObjects.Add(nearbyObject);
}
WorldObject closestObject = WorkManager.FindNearestWorldObjectInListToPosition(enemyObjects, currentPosition);
if (closestObject)
{
attacking = true;
//agent.isStopped = true;
BeginAttack(closestObject);
}
}
}
public Player GetPlayer()
{
return player;
}
protected virtual void OnGUI()
{
if (currentlySelected && !ResourceManager.MenuOpen) DrawSelection();
}
protected virtual void InitialiseAudio()
{
List<AudioClip> sounds = new List<AudioClip>();
List<float> volumes = new List<float>();
if (attackVolume < 0.0f) attackVolume = 0.0f;
if (attackVolume > 1.0f) attackVolume = 1.0f;
sounds.Add(attackSound);
volumes.Add(attackVolume);
if (selectVolume < 0.0f) selectVolume = 0.0f;
if (selectVolume > 1.0f) selectVolume = 1.0f;
sounds.Add(selectSound);
volumes.Add(selectVolume);
if (useWeaponVolume < 0.0f) useWeaponVolume = 0.0f;
if (useWeaponVolume > 1.0f) useWeaponVolume = 1.0f;
sounds.Add(useWeaponSound);
volumes.Add(useWeaponVolume);
audioElement = new AudioElement(sounds, volumes, objectName + ObjectId, this.transform);
}
public void SetPlayer()
{
player = transform.root.GetComponentInChildren<Player>();
}
public bool IsOwnedBy(Player owner)
{
if (player && player.Equals(owner))
{
return true;
}
else
{
return false;
}
}
public void CalculateBounds()
{
selectionBounds = new Bounds(transform.position, Vector3.zero);
foreach (Renderer r in GetComponentsInChildren<Renderer>())
{
selectionBounds.Encapsulate(r.bounds);
}
}
//!!!!!MULTI SELECTION!!!!!
public virtual void SetSelection(bool selected, Rect playingArea)
{
currentlySelected = selected;
if (selected)
{
if (audioElement != null) audioElement.Play(selectSound);
this.playingArea = playingArea;
}
CalculateBounds();
}
//!!!!!MULTI SELECTION!!!!!
public Bounds GetSelectionBounds()
{
return selectionBounds;
}
public string[] GetActions()
{
return actions;
}
public void SetColliders(bool enabled)
{
Collider[] colliders = GetComponentsInChildren<Collider>();
foreach (Collider collider in colliders) collider.enabled = enabled;
}
public void SetTransparentMaterial(Material material, bool storeExistingMaterial)
{
if (storeExistingMaterial) oldMaterials.Clear();
Renderer[] renderers = GetComponentsInChildren<Renderer>();
foreach (Renderer renderer in renderers)
{
if (storeExistingMaterial) oldMaterials.Add(renderer.material);
renderer.material = material;
}
}
public void RestoreMaterials()
{
Renderer[] renderers = GetComponentsInChildren<Renderer>();
if (oldMaterials.Count == renderers.Length)
{
for (int i = 0; i < renderers.Length; i++)
{
renderers[i].material = oldMaterials[i];
}
}
}
public void SetPlayingArea(Rect playingArea)
{
this.playingArea = playingArea;
}
public virtual void SetHoverState(GameObject hoverObject)
{
//only handle input if owned by a human player and currently selected
if (player && player.human && currentlySelected)
{
//something other than the ground is being hovered over
if (hoverObject.name != "Ground")
{
Player owner = hoverObject.transform.root.GetComponent<Player>();
Unit unit = hoverObject.transform.parent.GetComponent<Unit>();
Building building = hoverObject.transform.parent.GetComponent<Building>();
if (owner)
{ //the object is owned by a player
if (owner.username == player.username) player.hud.SetCursorState(CursorState.Select);
else if (CanAttack()) player.hud.SetCursorState(CursorState.Attack);
else player.hud.SetCursorState(CursorState.Select);
}
else if (unit || building && CanAttack()) player.hud.SetCursorState(CursorState.Attack);
else player.hud.SetCursorState(CursorState.Select);
}
}
}
public virtual bool CanAttack()
{
//default behaviour needs to be overidden by children
return false;
}
public virtual void PerformAction(string actionToPerform)
{
//it is up to children with specific actions to determine what to do with each of those actions
}
public virtual void MouseClick(GameObject hitObject, Vector3 hitPoint, Player controller)
{
//only handle input if currently selected
if (currentlySelected && hitObject && hitObject.name != "Ground")
{
WorldObject worldObject = hitObject.transform.parent.GetComponent<WorldObject>();
//clicked on another selectable object
if (worldObject)
{
Resource resource = hitObject.transform.parent.GetComponent<Resource>();
if (resource && resource.isEmpty()) return;
Player owner = hitObject.transform.root.GetComponent<Player>();
if (owner)
{ //the object is controlled by a player
if (player && player.human)
{ //this object is controlled by a human player
//start attack if object is not owned by the same player and this object can attack, else select
if (player.username != owner.username && CanAttack())
{
BeginAttack(worldObject);
}
else ChangeSelection(worldObject, controller);
}
else ChangeSelection(worldObject, controller);
}
else ChangeSelection(worldObject, controller);
}
}
}
protected virtual void BeginAttack(WorldObject target)
{
//if (audioElement != null) audioElement.Play(attackSound);
this.target = target;
if (TargetInRange())
{
anim.SetBool("Attacking", true);
attacking = true;
PerformAttack();
}
else AdjustPosition();
}
protected void SetTeamColor()
{
TeamColor[] teamColors = GetComponentsInChildren<TeamColor>();
foreach (TeamColor teamColor in teamColors) teamColor.GetComponent<Renderer>().material.color = player.teamColor;
}
protected virtual void DrawSelectionBox(Rect selectBox)
{
GUI.Box(selectBox, "");
CalculateCurrentHealth(0.35f, 0.65f);
DrawHealthBar(selectBox, "");
}
protected virtual void CalculateCurrentHealth(float lowSplit, float highSplit)
{
healthPercentage = (float)hitPoints / (float)maxHitPoints;
if (healthPercentage > highSplit) healthStyle.normal.background = ResourceManager.HealthyTexture;
else if (healthPercentage > lowSplit) healthStyle.normal.background = ResourceManager.DamagedTexture;
else healthStyle.normal.background = ResourceManager.CriticalTexture;
}
protected void DrawHealthBar(Rect selectBox, string label)
{
healthStyle.padding.top = -20;
healthStyle.fontStyle = FontStyle.Bold;
GUI.Label(new Rect(selectBox.x, selectBox.y - 7, selectBox.width * healthPercentage, 5), label, healthStyle);
}
protected virtual void AimAtTarget()
{
aiming = true;
//this behaviour needs to be specified by a specific object
}
private void ChangeSelection(WorldObject worldObject, Player controller)
{
//this should be called by the following line, but there is an outside chance it will not
SetSelection(false, playingArea);
if (controller.SelectedObject) controller.SelectedObject.SetSelection(false, playingArea);
controller.SelectedObject = worldObject;
worldObject.SetSelection(true, controller.hud.GetPlayingArea());
}
private void DrawSelection()
{
GUI.skin = ResourceManager.SelectBoxSkin;
Rect selectBox = WorkManager.CalculateSelectionBox(selectionBounds, playingArea);
//Draw the selection box around the currently selected object, within the bounds of the playing area
GUI.BeginGroup(playingArea);
DrawSelectionBox(selectBox);
GUI.EndGroup();
}
private bool TargetInRange()
{
Vector3 targetLocation = target.transform.position;
Vector3 direction = targetLocation - transform.position;
if (direction.sqrMagnitude < weaponRange * weaponRange)
{
return true;
}
return false;
}
private void AdjustPosition()
{
Unit self = this as Unit;
if (self)
{
movingIntoPosition = true;
Vector3 attackPosition = FindNearestAttackPosition();
self.StartMove(attackPosition);
attacking = true;
}
else
{
attacking = false;
}
}
private Vector3 FindNearestAttackPosition()
{
Vector3 targetLocation = target.transform.position;
Vector3 direction = targetLocation - transform.position;
float targetDistance = direction.magnitude;
float distanceToTravel = targetDistance - (0.9f * weaponRange);
return Vector3.Lerp(transform.position, targetLocation, distanceToTravel / targetDistance);
}
private void PerformAttack()
{
if (!target)
{
attacking = false;
anim.SetBool("Attacking", false);
anim.SetBool("IsRunning", false);
return;
}
if (!TargetInRange())
{
AdjustPosition();
}
else if (!TargetInFrontOfWeapon())
{
AimAtTarget();
}
else if (ReadyToFire())
{
//attacking = true;
UseWeapon();
}
//if (TargetInRange() && (attacking = true))
//{
// AdjustPosition();
//}
}
private bool TargetInFrontOfWeapon()
{
Vector3 targetLocation = target.transform.position;
Vector3 direction = targetLocation - transform.position;
if (direction.normalized == transform.forward.normalized) return true;
else return false;
}
private bool ReadyToFire()
{
if (currentWeaponChargeTime >= weaponRechargeTime)
{
return true;
}
return false;
}
protected virtual void UseWeapon()
{
if (audioElement != null && Time.timeScale > 0) audioElement.Play(useWeaponSound);
currentWeaponChargeTime = 0.0f;
//this behaviour needs to be specified by a specific object
}
public void TakeDamage(float damage)
{
//GameObject.Instantiate(impactVisual, target.transform.position, Quaternion.identity);
hitPoints -= damage;
if (hitPoints <= 0)
{
Instantiate(explosionPrefab, transform.position + new Vector3(0, 5, 0), Quaternion.identity);
Instantiate(splat, transform.position, Quaternion.identity);
Destroy(gameObject);
}
}
}
using UnityEngine;
using System.Collections.Generic;
namespace RTS
{
public static class WorkManager
{
public static Rect CalculateSelectionBox(Bounds selectionBounds, Rect playingArea)
{
//shorthand for the coordinates of the centre of the selection bounds
float cx = selectionBounds.center.x;
float cy = selectionBounds.center.y;
float cz = selectionBounds.center.z;
//shorthand for the coordinates of the extents of the selection bounds
float ex = selectionBounds.extents.x;
float ey = selectionBounds.extents.y;
float ez = selectionBounds.extents.z;
//Determine the screen coordinates for the corners of the selection bounds
List<Vector3> corners = new List<Vector3>();
corners.Add(Camera.main.WorldToScreenPoint(new Vector3(cx + ex, cy + ey, cz + ez)));
corners.Add(Camera.main.WorldToScreenPoint(new Vector3(cx + ex, cy + ey, cz - ez)));
corners.Add(Camera.main.WorldToScreenPoint(new Vector3(cx + ex, cy - ey, cz + ez)));
corners.Add(Camera.main.WorldToScreenPoint(new Vector3(cx - ex, cy + ey, cz + ez)));
corners.Add(Camera.main.WorldToScreenPoint(new Vector3(cx + ex, cy - ey, cz - ez)));
corners.Add(Camera.main.WorldToScreenPoint(new Vector3(cx - ex, cy - ey, cz + ez)));
corners.Add(Camera.main.WorldToScreenPoint(new Vector3(cx - ex, cy + ey, cz - ez)));
corners.Add(Camera.main.WorldToScreenPoint(new Vector3(cx - ex, cy - ey, cz - ez)));
//Determine the bounds on screen for the selection bounds
Bounds screenBounds = new Bounds(corners[0], Vector3.zero);
for (int i = 1; i < corners.Count; i++)
{
screenBounds.Encapsulate(corners[i]);
}
//Screen coordinates start in the bottom left corner, rather than the top left corner
//this correction is needed to make sure the selection box is drawn in the correct place
float selectBoxTop = playingArea.height - (screenBounds.center.y + screenBounds.extents.y);
float selectBoxLeft = screenBounds.center.x - screenBounds.extents.x;
float selectBoxWidth = 2 * screenBounds.extents.x;
float selectBoxHeight = 2 * screenBounds.extents.y;
return new Rect(selectBoxLeft, selectBoxTop, selectBoxWidth, selectBoxHeight);
}
public static GameObject FindHitObject(Vector3 origin)
{
Ray ray = Camera.main.ScreenPointToRay(origin);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, ResourceManager.RayCastLimit)) return hit.collider.gameObject;
return null;
}
public static Vector3 FindHitPoint(Vector3 origin)
{
Ray ray = Camera.main.ScreenPointToRay(origin);
RaycastHit hit;
Debug.DrawRay(ray.origin, ray.direction * ResourceManager.RayCastLimit, Color.yellow);
if (Physics.Raycast(ray, out hit, ResourceManager.RayCastLimit)) return hit.point;
return ResourceManager.InvalidPosition;
}
public static List<WorldObject> FindNearbyObjects(Vector3 position, float range)
{
Collider[] hitColliders = Physics.OverlapSphere(position, range);
HashSet<int> nearbyObjectIds = new HashSet<int>();
List<WorldObject> nearbyObjects = new List<WorldObject>();
for (int i = 0; i < hitColliders.Length; i++)
{
Transform parent = hitColliders[i].transform.parent;
if (parent)
{
WorldObject parentObject = parent.GetComponent<WorldObject>();
if (parentObject && !nearbyObjectIds.Contains(parentObject.ObjectId))
{
nearbyObjectIds.Add (parentObject.ObjectId);
nearbyObjects.Add (parentObject);
}
}
}
return nearbyObjects;
}
public static WorldObject FindNearestWorldObjectInListToPosition(List<WorldObject> objects, Vector3 position)
{
if (objects == null || objects.Count == 0) return null;
WorldObject nearestObject = objects[0];
float sqrDistanceToNearestObject = Vector3.SqrMagnitude(position - nearestObject.transform.position);
for (int i = 1; i < objects.Count; i++)
{
float sqrDistanceToObject = Vector3.SqrMagnitude(position - objects[i].transform.position);
if (sqrDistanceToObject < sqrDistanceToNearestObject)
{
sqrDistanceToNearestObject = sqrDistanceToObject;
nearestObject = objects[i];
}
}
return nearestObject;
}
}
}
The first thing you need to check is if inside
FindNearbyObjects()
The variable
hitColliders = Physics.OverlapSphere(position, range);
Changes it's size when you instantiate new buildings. In case that is not the case, it may be because you are not adding colliders to the buildings when you instantiate them.
However, I think there are better ways for you to detect buildings without using this Physics.OverlapSphere(), which may be expensive in performance. If I were you I will would give a special tag to the buildings (the original and the instantiated ones) and I will use that in my logic to detect them. So they will be potential targets in your method:
DecideWhatToDo()
Here you can read about how to tag the GameObjects:
https://docs.unity3d.com/Manual/Tags.html
I am new to coding and Unity
I have the health bar appearing on my screen, but I am not sure how to link the Health script of the health bar to my player script and my player's health script. Simply, I want to make it so when my player gets shot my health bar will lose a heart
my health bar script
using UnityEngine;
using System.Collections;
public class Health : MonoBehaviour {
public int startHealth;
public int healthPerHeart;
private int maxHealth;
private int currentHealth;
public Texture[] heartImages;
public GUITexture heartGUI;
private ArrayList hearts = new ArrayList();
// Spacing:
public float maxHeartsOnRow;
private float spacingX;
private float spacingY;
void Start () {
spacingX = heartGUI.pixelInset.width;
spacingY = -heartGUI.pixelInset.height;
AddHearts(startHealth/healthPerHeart);
}
public void AddHearts(int n) {
for (int i = 0; i <n; i ++) {
Transform newHeart = ((GameObject)Instantiate(heartGUI.gameObject,this.transform.position,Quaternion.identity)).transform; // Creates a new heart
newHeart.parent = transform;
int y = (int)(Mathf.FloorToInt(hearts.Count / maxHeartsOnRow));
int x = (int)(hearts.Count - y * maxHeartsOnRow);
newHeart.GetComponent<GUITexture>().pixelInset = new Rect(x * spacingX,y * spacingY,58,58);
newHeart.GetComponent<GUITexture>().texture = heartImages[0];
hearts.Add(newHeart);
}
maxHealth += n * healthPerHeart;
currentHealth = maxHealth;
UpdateHearts();
}
public void modifyHealth(int amount) {
currentHealth += amount;
currentHealth = Mathf.Clamp(currentHealth,0,maxHealth);
UpdateHearts();
}
void UpdateHearts() {
bool restAreEmpty = false;
int i =0;
foreach (Transform heart in hearts) {
if (restAreEmpty) {
heart.guiTexture.texture = heartImages[0]; // heart is empty
}
else {
i += 1; // current iteration
if (currentHealth >= i * healthPerHeart) {
heart.guiTexture.texture = heartImages[heartImages.Length-1]; // health of current heart is full
}
else {
int currentHeartHealth = (int)(healthPerHeart - (healthPerHeart * i - currentHealth));
int healthPerImage = healthPerHeart / heartImages.Length; // how much health is there per image
int imageIndex = currentHeartHealth / healthPerImage;
if (imageIndex == 0 && currentHeartHealth > 0) {
imageIndex = 1;
}
heart.guiTexture.texture = heartImages[imageIndex];
restAreEmpty = true;
}
}
}
}
}
my player script
/// <summary>
/// Player controller and behavior
/// </summary>
public class PlayerScript : MonoBehaviour
{
public Health health;
/// <summary>
/// 1 - The speed of the ship
/// </summary>
public Vector2 speed = new Vector2(50, 50);
// 2 - Store the movement
private Vector2 movement;
void OnCollisionEnter2D(Collision2D collision)
{
bool damagePlayer = false;
// Collision with enemy
EnemyScript enemy = collision.gameObject.GetComponent<EnemyScript>();
if (enemy != null)
{
// Kill the enemy
HealthScript enemyHealth = enemy.GetComponent<HealthScript>();
if (enemyHealth != null) enemyHealth.Damage(enemyHealth.hp);
damagePlayer = true;
}
// Damage the player
if (damagePlayer)
{
HealthScript playerHealth = this.GetComponent<HealthScript>();
if (playerHealth != null) playerHealth.Damage(1);
}
}
void Update()
{
// 3 - Retrieve axis information
float inputX = Input.GetAxis("Horizontal");
float inputY = Input.GetAxis("Vertical");
// 4 - Movement per direction
movement = new Vector2(
speed.x * inputX,
speed.y * inputY);
// 5 - Shooting
bool shoot = Input.GetButtonDown("Fire1");
shoot |= Input.GetButtonDown("Fire2");
// Careful: For Mac users, ctrl + arrow is a bad idea
if (shoot)
{
WeaponScript weapon = GetComponent<WeaponScript>();
if (weapon != null)
{
// false because the player is not an enemy
weapon.Attack(false);
}
}
// 6 - Make sure we are not outside the camera bounds
var dist = (transform.position - Camera.main.transform.position).z;
var leftBorder = Camera.main.ViewportToWorldPoint(
new Vector3(0, 0, dist)
).x;
var rightBorder = Camera.main.ViewportToWorldPoint(
new Vector3(1, 0, dist)
).x;
var topBorder = Camera.main.ViewportToWorldPoint(
new Vector3(0, 0, dist)
).y;
var bottomBorder = Camera.main.ViewportToWorldPoint(
new Vector3(0, 1, dist)
).y;
transform.position = new Vector3(
Mathf.Clamp(transform.position.x, leftBorder, rightBorder),
Mathf.Clamp(transform.position.y, topBorder, bottomBorder),
transform.position.z
);
}
void FixedUpdate()
{
// 5 - Move the game object
rigidbody2D.velocity = movement;
}
void OnDestroy()
{
Application.LoadLevel("gameOver");
}
}
and my player's health script
using UnityEngine;
/// <summary>
/// Handle hitpoints and damages
/// </summary>
public class HealthScript : MonoBehaviour
{
/// <summary>
/// Total hitpoints
/// </summary>
public int hp = 1;
/// <summary>
/// Enemy or player?
/// </summary>
public bool isEnemy = true;
/// <summary>
/// Inflicts damage and check if the object should be destroyed
/// </summary>
/// <param name="damageCount"></param>
public void Damage(int damageCount)
{
hp -= damageCount;
if (hp <= 0)
{
// 'Splosion!
SpecialEffectsHelper.Instance.Explosion(transform.position);
// Dead!
Destroy(gameObject);
}
}
void OnTriggerEnter2D(Collider2D otherCollider)
{
// Is this a shot?
ShotScript shot = otherCollider.gameObject.GetComponent<ShotScript>();
if (shot != null)
{
// Avoid friendly fire
if (shot.isEnemyShot != isEnemy)
{
Damage(shot.damage);
// Destroy the shot
Destroy(shot.gameObject); // Remember to always target the game object, otherwise you will just remove the script
}
}
}
}
With new UI system in Unity 4.6 it is really easy to create a health bar.
GameObject->UI->Image
Put your health bar sprite in image.
Change the Image type to Filled. Then you can play with Fill amount property and also control in through code
In your PlayerScript you retrieve the HealthScript with the following code:
HealthScript playerHealth = this.GetComponent<HealthScript>();
If you want to call methods on the Health script you would do something similar.
Health healthBar = this.GetComponent<Health>();
healthBar.modifyHealth(amountOfDamage);
This assumes all 3 scripts are on the same Game object.
I'm using Roslyn from Sep 2012. I'm trying to create instance of a class from file. Problem is that the class is implementing and overriding some methods. When I try to run a run-time compile a get errors like:
error CS0122: 'GameObject' is inaccessible due to its protection level Roslyn.Compilers.CSharp.Diagnostic
error CS0115: 'rotate(float)': no suitable method found to override Roslyn.Compilers.CSharp.Diagnostic
It looks like class doesn't see interface and overriding functions. But my Compilation looks:
var comp = Compilation.Create("Test.dll"
, syntaxTrees: new[] { syntaxTree }
, references: new[] {
MetadataFileReference.CreateAssemblyReference("mscorlib"),
new MetadataFileReference(typeof(Game.IGameObjectInterface).Assembly.Location),
new MetadataFileReference(typeof(Team).Assembly.Location),
new MetadataFileReference(typeof(System.Linq.Enumerable).Assembly.Location),
new MetadataFileReference(typeof(LinkedList<>).Assembly.Location),
}
, options: new CompilationOptions(OutputKind.DynamicallyLinkedLibrary)
);
Reference on the interface is added.
What am I doing wrong?
EDIT GameObject
abstract class GameObject: IGameObject {
protected string name;
protected Entity entity;
.
.
.
//Look here create file load file
static GameObject() {
gameActionsPermitions = new Dictionary<string, List<IStaticGameObject>>();
gameActions = new Dictionary<string, IGameAction>();
IGameAction o = (IGameAction)System.Reflection.Assembly.GetExecutingAssembly().CreateInstance("Strategy.GroupControl.Game_Objects.GameActions.Produce");
gameActions.Add(o.getName(), o);
gameActionsPermitions.Add(o.getName(), new List<IStaticGameObject>());
}
.
.
.
public abstract void rotate(float f);
public abstract void nonActiveRotate(float f);
protected abstract void onDisplayed();
.
.
.
}
And inteface IGameObject
interface IGameObject{
void rotate(float f);
void nonActiveRotate(float f);
void changeVisible(bool visible);
string getName();
string getMesh();
bool tryExecute(string executingAction);
Team Team { get; set; }
}
And function from file is
public override void rotate(float f) {
tryExecute("Produce");
sceneNode.Roll(new Mogre.Degree((float)(mFlySpeed * 0.5 *f)));
//position in LinkedList now moving
if (!mFlying) {
if (nextLocation()) {
mFlying = true;
mDestination = circularPositions.First.Value; //get the next destination.
prepareNextPosition();
//update the direction and the distance
mDirection = mDestination - sceneNode.Position;
mDistance = mDirection.Normalise();
} else {
}//nothing to do so stay in position
} else {
double move = mFlySpeed * f;
mDistance -= move;
if (mDistance <= .0f) { //reach destination
travelledInvisible = 0;
sceneNode.Position = mDestination;
mDirection = Mogre.Vector3.ZERO;
mFlying = false;
} else {
sceneNode.Translate(mDirection * (float)move);
}
}
}
EDIT2:
file with class
using System;
using System.Collections.Generic;
using System.Linq;
using Mogre;
using Strategy.TeamControl;
namespace Strategy.GroupControl.Game_Objects.StaticGameObjectBox {
class Planet : GameObject {
protected double mDistance = 0.0f; //distance to positoin
protected Mogre.Vector3 mDirection = Mogre.Vector3.ZERO; // The direction the object is moving
protected bool mFlying = false; //bool to detect if object walking or stay
protected double mFlySpeed = 200f; //speed of planet
protected double travelledInvisible;
private static Random random = new Random();
///testing
public Planet() {
}
public Planet(string s) {
name = s;
}
//end
public Planet(string name, string mesh, Team myTeam, Mogre.SceneManager manager, double distanceFromCenter,
Vector3 center, int circularNum = 30) {
this.name = name;
this.mesh = mesh;
planetTeam = myTeam;
this.manager = manager;
//prepare list of positions
circularPositions = calculatePositions(circularNum, distanceFromCenter,center);
randomizeStartPosition(circularNum); // randomize start position
mDestination = circularPositions.First();
//Mogre inicialization of object
entity = manager.CreateEntity(name, mesh);
}
/// <summary>
/// Rotating in visible mood, it means when planet is in active solar system
/// </summary>
/// <param name="f">delay between frames</param>
public override void rotate(float f) {
tryExecute("Produce");
sceneNode.Roll(new Mogre.Degree((float)(mFlySpeed * 0.5 *f)));
//position in LinkedList now moving
if (!mFlying) {
if (nextLocation()) {
mFlying = true;
mDestination = circularPositions.First.Value; //get the next destination.
prepareNextPosition();
//update the direction and the distance
mDirection = mDestination - sceneNode.Position;
mDistance = mDirection.Normalise();
} else {
}//nothing to do so stay in position
} else {
double move = mFlySpeed * f;
mDistance -= move;
if (mDistance <= .0f) { //reach destination
travelledInvisible = 0;
sceneNode.Position = mDestination;
mDirection = Mogre.Vector3.ZERO;
mFlying = false;
} else {
sceneNode.Translate(mDirection * (float)move);
}
}
}
/// <summary>
/// Function calculate moves in invisible mode
/// </summary>
/// <param name="f">delay between frames</param>
public override void nonActiveRotate(float f) {
tryExecute("Produce");
if (!mFlying) {
if (nextLocation()) {
mFlying = true;
mDestination = circularPositions.First.Value; //get the next destination.
prepareNextPosition();
mDistance = mDirection.Normalise();
} else {
}//nothing to do so stay in position
} else {
double move = mFlySpeed * f;
mDistance -= move;
if (mDistance <= .0f) { //reach destination
travelledInvisible = 0;
mDirection = Mogre.Vector3.ZERO;
mFlying = false;
} else {
travelledInvisible += move;
}
}
}
//own functions
/// <summary>
/// Randomize starting position of planet
/// </summary>
/// <param name="max">max of rotates</param>
private void randomizeStartPosition(int max) {
for (int i = 0; i < getRandomNumber(max); i++) {
prepareNextPosition();
}
}
private static int getRandomNumber(int max) {
return random.Next(max);
}
/// <summary>
/// Cyclic remove from LinkedList and add on the end
/// </summary>
private void prepareNextPosition() {
var tmp = circularPositions.First; //save the node that held it
circularPositions.RemoveFirst(); //remove that node from the front of the list
circularPositions.AddLast(tmp); //add it to the back of the list.
}
/// <summary>
/// Calculate posistion on circle represent as ngon
/// </summary>
/// <param name="circularNum">Number of positions on circle</param>
/// <param name="distanceFromCenter">radius on circle</param>
/// <returns>linkedList with position on ngon (circle)</returns>
private LinkedList<Mogre.Vector3> calculatePositions(int circularNum, double distanceFromCenter,Vector3 center) {
var list = new LinkedList<Mogre.Vector3>();
for (int i = 0; i < circularNum; i++) {
double x = System.Math.Cos(i * 2 * System.Math.PI / circularNum) * distanceFromCenter;
double y = System.Math.Sin(i * 2 * System.Math.PI / circularNum) * distanceFromCenter;
list.AddFirst(new Mogre.Vector3((float)x + center.x, 0, (float)y)+ center.y);
}
return list;
}
/// <summary>
/// The NextLocation() check if exist next location to move
/// </summary>
/// <returns>true ->exist / false -> not exist</returns>
private bool nextLocation() {
if (circularPositions.Count == 0) {
return false;
}
return true;
}
/// <summary>
/// Called when object is displayed (invisible to visible)
/// </summary>
protected override void onDisplayed() {
sceneNode.Position = mDestination;
mFlying = false; //jump correction
}
}
}
These look like standard compiler errors.
I suspect your GameObject class is not declared as public. This will cause it to not be visible to the assembly you're creating via Roslyn, as it's compiling a new (separate) assembly from the one in which your types are defined.
If you make your types public, this error will likely go away.
I'm making a game using XNA 4.0 and c#.
I just made my camera class and it's almost working as expected, except for one thing.
I can move with my mouse to rotate the camera but the problem is that when I get to the border of the screen, the mouse stops and so does the camera movement.
Is there any way to allow the mouse pointer to be outside of the screens boundaries to be able to keep tracking the pointer? Or is there any simpler way around?
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
public class ArcBallCamera
{
private float speeder = 100;
public ArcBallCamera(float aspectRation, Vector3 lookAt)
: this(aspectRation, MathHelper.PiOver4, lookAt, Vector3.Up, 0.1f, float.MaxValue) { }
public ArcBallCamera(float aspectRatio, float fieldOfView, Vector3 lookAt, Vector3 up, float nearPlane, float farPlane)
{
this.aspectRatio = aspectRatio;
this.fieldOfView = fieldOfView;
this.lookAt = lookAt;
this.nearPlane = nearPlane;
this.farPlane = farPlane;
}
/// <summary>
/// Recreates our view matrix, then signals that the view matrix
/// is clean.
/// </summary>
public void ReCreateViewMatrix()
{
//Calculate the relative position of the camera
position = Vector3.Transform(Vector3.Backward, Matrix.CreateFromYawPitchRoll(yaw, pitch, 0));
//Convert the relative position to the absolute position
position *= zoom;
position += lookAt;
//Calculate a new viewmatrix
viewMatrix = Matrix.CreateLookAt(position, lookAt, Vector3.Up);
viewMatrixDirty = false;
}
/// <summary>
/// Recreates our projection matrix, then signals that the projection
/// matrix is clean.
/// </summary>
public void ReCreateProjectionMatrix()
{
projectionMatrix = Matrix.CreatePerspectiveFieldOfView(fieldOfView, AspectRatio, nearPlane, farPlane);
projectionMatrixDirty = false;
}
#region HelperMethods
/// <summary>
/// Moves the camera and lookAt at to the right,
/// as seen from the camera, while keeping the same height
/// </summary>
public void MoveCameraRight(float amount)
{
Vector3 right = Vector3.Normalize(LookAt - Position); //calculate forward
right = Vector3.Cross(right, Vector3.Up); //calculate the real right
//right.Y = 0;
right.Normalize();
LookAt += right * amount;
}
/// <summary>
/// Moves the camera and lookAt forward,
/// as seen from the camera, while keeping the same height
/// </summary>
public void MoveCameraForward(float amount)
{
Vector3 forward = Vector3.Normalize(LookAt - Position);
// forward.Y = 0;
forward.Normalize();
LookAt += forward * amount;
}
/// <summary>
/// Moves the camera and lookAt up or down,
/// LOL
/// </summary>
public void MoveCameraUp(float amount)
{
Vector3 up = Vector3.Normalize(LookAt - position);
up = Vector3.Cross(up, Vector3.Left); //Calculate the REAL FUCKING UP/DOWN
up.X = 0;
up.Z = 0;
up.Normalize();
LookAt += up * amount;
}
#endregion
#region FieldsAndProperties
//We don't need an update method because the camera only needs updating
//when we change one of it's parameters.
//We keep track if one of our matrices is dirty
//and reacalculate that matrix when it is accesed.
private bool viewMatrixDirty = true;
private bool projectionMatrixDirty = true;
public float MinPitch = -MathHelper.PiOver2 + 0.3f;
public float MaxPitch = MathHelper.PiOver2 - 0.3f;
private float pitch;
public float Pitch
{
get { return pitch; }
set
{
viewMatrixDirty = true;
pitch = MathHelper.Clamp(value, MinPitch, MaxPitch);
}
}
private float yaw;
public float Yaw
{
get { return yaw; }
set
{
viewMatrixDirty = true;
yaw = value;
}
}
private float fieldOfView;
public float FieldOfView
{
get { return fieldOfView; }
set
{
projectionMatrixDirty = true;
fieldOfView = value;
}
}
private float aspectRatio;
public float AspectRatio
{
get { return aspectRatio; }
set
{
projectionMatrixDirty = true;
aspectRatio = value;
}
}
private float nearPlane;
public float NearPlane
{
get { return nearPlane; }
set
{
projectionMatrixDirty = true;
nearPlane = value;
}
}
private float farPlane;
public float FarPlane
{
get { return farPlane; }
set
{
projectionMatrixDirty = true;
farPlane = value;
}
}
public float MinZoom = 1;
public float MaxZoom = float.MaxValue;
private float zoom = 1;
public float Zoom
{
get { return zoom; }
set
{
viewMatrixDirty = true;
zoom = MathHelper.Clamp(value, MinZoom, MaxZoom);
}
}
private Vector3 position;
public Vector3 Position
{
get
{
if (viewMatrixDirty)
{
ReCreateViewMatrix();
}
return position;
}
}
private Vector3 lookAt;
public Vector3 LookAt
{
get { return lookAt; }
set
{
viewMatrixDirty = true;
lookAt = value;
}
}
#endregion
#region ICamera Members
public Matrix ViewProjectionMatrix
{
get { return ViewMatrix * ProjectionMatrix; }
}
private Matrix viewMatrix;
public Matrix ViewMatrix
{
get
{
if (viewMatrixDirty)
{
ReCreateViewMatrix();
}
return viewMatrix;
}
}
private Matrix projectionMatrix;
public Matrix ProjectionMatrix
{
get
{
if (projectionMatrixDirty)
{
ReCreateProjectionMatrix();
}
return projectionMatrix;
}
}
#endregion
}
You can reset the mouse position for every frame.
Example:
// Center of the window
var resetPosition = new Point(WindowWidth / 2, WindowHeight / 2);
// Get the movement since the last frame
var mouseState = Mouse.GetState();
var mousePosition = new Point(mouseState.X, mouseState.Y);
var delta = mousePosition - resetPosition;
// Reset the mouse position
Mouse.SetPosition(resetPosition.X, resetPosition.Y);
// Use the delta
RotateCamera(delta);