C# procedural generation- how to do always a set number? - c#

Ok, Working in Unity here and trying to get out this core game dynamic. Basically I have all these 3D platforms that have certain weights to them (weight meaning how often they appear in the array from which game can select next platform) -
right now each platform has a set of the 4 cardinal directions (plus up/down but all have those) where it can spawn the next platform for player to walk onto, else they fall. This is an enum and I set this manually.
Before player first steps on a platform, it is halfway alpha, so it just looks like a marker. After they step, it turns 1 alpha and thus doesn't look like a "marker", see here:
As the player walks via joystick, I want the platforms to spawn in square "tiers" - say of length 10 platforms - and I'll do something when tier is full. My problem is I've tried a bunch of different systems but do not know how to implement this. Model picture where there are different configurations but ultimately a 10x10 limit/bounds:
Here's my method of spawning based on direction - problem is direction is subjective, based on player object's point of view:
foreach(Direction d in directionsAvailable)
{
Vector3 pos = transform.position;
float dist = container.GetComponent<Renderer> ().bounds.size.x;
switch (d) {
case Direction.Backward:
pos = new Vector3 (pos.x, pos.y, pos.z-dist);
break;
case Direction.Forward:
pos = new Vector3 (pos.x, pos.y, pos.z+dist);
break;
case Direction.Left:
pos = new Vector3 (pos.x-dist, pos.y, pos.z);
break;
case Direction.Right:
pos = new Vector3 (pos.x+dist, pos.y, pos.z);
break;
case Direction.Down:
pos = new Vector3 (pos.x, pos.y-(2*dist), pos.z);
break;
case Direction.Up:
pos = new Vector3 (pos.x, pos.y+(2*dist), pos.z); //hits itself, might have to do more dist
break;
default:
break;
}
Here is how I test if a platform is at a position or position is open:
public Platform PlatAtPos(Vector3 pos)
{
platformsSpawned = GameObject.FindObjectsOfType<Platform>();
foreach(Platform p in platformsSpawned)
{
if(p.originPos == pos || p.transform.position == pos) //or just delete one of them
{
return p;
}
}
return null;
}
public void checkForPlatsAround()
{
gameController = GameObject.FindObjectOfType<GameController> ();
float dist = container.GetComponent<Renderer> ().bounds.size.x;
foreach (Platform.Direction dir in Enum.GetValues(typeof(Platform.Direction))) {
Vector3 pos = transform.position;
switch (dir) {
case Direction.Backward:
pos = new Vector3 (pos.x, pos.y, pos.z-dist);
break;
case Direction.Forward:
pos = new Vector3 (pos.x, pos.y, pos.z+dist);
break;
case Direction.Left:
pos = new Vector3 (pos.x-dist, pos.y, pos.z);
break;
case Direction.Right:
pos = new Vector3 (pos.x+dist, pos.y, pos.z);
break;
case Direction.Down:
pos = new Vector3 (pos.x, pos.y-(2*dist), pos.z);
break;
case Direction.Up:
pos = new Vector3 (pos.x, pos.y+(2*dist), pos.z); //hits itself, might have to do more dist
break;
default:
break;
}
if(gameController.PlatAtPos(pos) != null)
{
gameController.PlatAtPos (pos).showAsMarker ();
}
}
}
Is there a better/clearer way to go about this? How can I do this procedurally?

Related

How to make object point and shoot another object?

asd.peeneje
Hello friends! I'm developing a game 2d platformer in #Unity, I need to make this object on the right side look at the other object on the left side and shoot in his direction. I don't know to do this. Can you help me in this? :D
I'm maked multiple attempts and I haven't made it. I try with this
if(isPointer) {
targetRotation = pointer.transform.position - transform.position;
angle = Mathf.Atan2(targetRotation.y, targetRotation.x) * Mathf.Rad2Deg;
gun.rotation = Quaternion.Euler(new Vector3(0,0, angle));
break;
}
void Shoot () {
if(shootTimer <= 0f) {
var Ball = Instantiate(ball, gun.position, transform.rotation, transform.parent);
var forward = transform.rotation * Vector3.forward;
targetRotation.z = 0;
if(isPointer) {
finalTarget = (forward.z * -transform.position).normalized;
break;
}
Ball.GetComponent<Rigidbody2D>().AddForce(finalTarget * speedBall, ForceMode2D.Impulse);
player.GetComponent<PlayerController>().ShootAni();
switch(weaponLoot1) {
case WeaponLoot1.glack:
shootTimer = 0.2f;
break;
case WeaponLoot1.silenced:
shootTimer = 0.2f;
break;
case WeaponLoot1.revolver:
shootTimer = 0.5f;
break;
case WeaponLoot1.shotgun:
shootTimer = 0.55f;
break;
case WeaponLoot1.mac10:
shootTimer = 0.15f;
break;
case WeaponLoot1.tommy:
shootTimer = 0.2f;
break;
case WeaponLoot1.ak47:
shootTimer = 0.2f;
break;
case WeaponLoot1.m4a1:
shootTimer = 0.2f;
break;
case WeaponLoot1.rifle:
shootTimer = 0.6f;
break;
case WeaponLoot1.bazooka:
shootTimer = 0.75f;
break;
}
}
}
You can use Quaternion.LookRotation
So you'll have
gun.rotation = Quaternion.LookRotation(pointer.transform.position - transform.position);

I want to make a method that returns the position the player is facing

I made a simple script to check what position the player is facing and put that in my animator
1 = up
2 = right
3 = down
4 = left
private Vector2 velocity;
private Animator animator;
private int direction;
private void Awake() {
animator = GetComponent<Animator>();
}
void Update(){
velocity.x = Input.GetAxisRaw("Horizontal");
velocity.y = Input.GetAxisRaw("Vertical");
switch(velocity){
case Vector2(0,1):
direction = 1;
break;
case Vector2(1,0):
direction = 2;
break;
case Vector2(0,-1):
direction = 3;
break;
case Vector2(-1,0):
direction = 4;
break;
}
animator.SetFloat("Facing",direction);
then I get the error
Assets/Scripts/PlayerMovement.cs(21,25): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'Vector2', with 2 out parameters and a void return type.
I believe your issue comes with how you are trying to use your switch statement as Vector(1,0) is attempting to call a function not actually reference the value you are looking a viable alternative is to use when like in the following example
case Vector2 v when v.Equals(Vector2.up):
Debug.Log("Up");
break;
case Vector2 v when v.Equals(Vector2.left):
Debug.Log("Left");
break;
case Vector2 v when v.Equals(Vector2.back):
Debug.Log("Back");
break;
case Vector2 v when v.Equals(Vector2.right):
Debug.Log("Right");
break;
I'm also using the shorthand up, left, right and down instead of defining the values manually
Assuming velocity is of type Vector2 you can't set the values of x and y as they are read-only properties.
Use this instead:
velocity = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
Vectors are structs and you can't create them without using new e.g. case new Vector2(0f, 1f):. There are some ready made shortcuts for direction built in that you can use:
if(velocity == Vector2.up)
{
print("direction = 1");
} else if (velocity == Vector2.right)
{
print("direction = 2");
} else if (velocity == Vector2.up)
{
print("direction = 3");
} else if (velocity == Vector2.down)
{
print("direction = 4");
} else if (velocity == Vector2.left)
{
print("direction = 1");
}

3D Compass in Hololens

I'm trying to develop a simple 3D Compass for Hololens 2, using Unity, but my sprites aren't aligned with the Cubes.
I wanted it to be like this: https://www.youtube.com/watch?v=3RuOq9ldX9g
If I move the cubes, the compass works as intended, but it still doesn't align with my FOV.
My code for getting the position on the compass is the following:
Vector2 GetPosOnCompass(QuestMarker marker)
{
Vector2 playerPos = new Vector2(Player.transform.position.x, Player.transform.position.z);
Vector2 playerFwd = new Vector2(Player.transform.forward.x, Player.transform.forward.z);
float angle = Vector2.SignedAngle(marker.position - playerPos, playerFwd);
return new Vector2(compassUnit * angle, 0f);
}
Best regards,
Carlos
This is the full Code:
using UnityEngine.UI;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Compass : MonoBehaviour
{
public GameObject iconPrefab;
List<QuestMarker> questMarkers = new List<QuestMarker>();
public RawImage CompassImage;
public Transform Player;
public Text CompassDirectionText;
float compassUnit;
public QuestMarker one;
public QuestMarker two;
public QuestMarker three;
private void Start()
{
compassUnit = CompassImage.rectTransform.rect.width / 360f;
AddQuestMarker(one);
AddQuestMarker(two);
AddQuestMarker(three);
}
public void Update()
{
foreach (QuestMarker marker in questMarkers)
{
marker.image.rectTransform.anchoredPosition = GetPosOnCompass(marker);
}
//Get a handle on the Image's uvRect
CompassImage.uvRect = new Rect(Player.localEulerAngles.y / 360, 0, 1, 1);
// Get a copy of your forward vector
Vector3 forward = Player.transform.forward;
// Zero out the y component of your forward vector to only get the direction in the X,Z plane
forward.y = 0;
//Clamp our angles to only 5 degree increments
float headingAngle = Quaternion.LookRotation(forward).eulerAngles.y;
headingAngle = 5 * (Mathf.RoundToInt(headingAngle / 5.0f));
//Convert float to int for switch
int displayangle;
displayangle = Mathf.RoundToInt(headingAngle);
//Set the text of Compass Degree Text to the clamped value, but change it to the letter if it is a True direction
switch (displayangle)
{
case 0:
//Do this
CompassDirectionText.text = "N";
break;
case 360:
//Do this
CompassDirectionText.text = "N";
break;
case 45:
//Do this
CompassDirectionText.text = "NE";
break;
case 90:
//Do this
CompassDirectionText.text = "E";
break;
case 130:
//Do this
CompassDirectionText.text = "SE";
break;
case 180:
//Do this
CompassDirectionText.text = "S";
break;
case 225:
//Do this
CompassDirectionText.text = "SW";
break;
case 270:
//Do this
CompassDirectionText.text = "W";
break;
default:
CompassDirectionText.text = headingAngle.ToString ();
break;
}
}
public void AddQuestMarker(QuestMarker marker)
{
GameObject newMarker = Instantiate(iconPrefab, CompassImage.transform);
marker.image = newMarker.GetComponent<Image>();
marker.image.sprite = marker.icon;
questMarkers.Add(marker);
}
Vector2 GetPosOnCompass(QuestMarker marker)
{
Vector2 playerPos = new Vector2(Player.transform.position.x, Player.transform.position.z);
Vector2 playerFwd = new Vector2(Player.transform.forward.x, Player.transform.forward.z);
float angle = Vector2.SignedAngle(marker.position - playerPos, playerFwd);
return new Vector2(compassUnit * angle, 0f);
}
}

Enable disable Rigidbody 2D when touch phase starts?

Hello im having a hard time trying to enable and disable the kinematic of a rigidbody 2d i have been doing some experiments but nothing seems to work out This is the code without my experiments on how to enable and disable
for the backgrounf im a doing a puzzle game 2d it uses the box collider 2d to match the pieces, i have many piecesand i want them to fall off with gravity , touch them and drag them to their spot , for that purpose i added a rigid body and it works perfectly for the falll , but i need it to be kinematic so i can drag it
[SerializeField]
private Transform El_carmenPlace;
private Vector2 initialPosition;
private float deltaX, deltaY;
public static bool locked;
private void Update()
{
if (Input.touchCount > 0 && !locked)
{
Touch touch = Input.GetTouch(0);
Vector2 touchPos = Camera.main.ScreenToWorldPoint(touch.position);
switch (touch.phase)
{
case TouchPhase.Began:
if (GetComponent<Collider2D>() == Physics2D.OverlapPoint(touchPos))
{
deltaX = touchPos.x - transform.position.x;
deltaY = touchPos.y - transform.position.y;
}
break;
case TouchPhase.Moved:
if (GetComponent<Collider2D>() == Physics2D.OverlapPoint(touchPos))
transform.position = new Vector2(touchPos.x - deltaX, touchPos.y - deltaY);
break;
case TouchPhase.Ended:
initialPosition = transform.position;
if (Mathf.Abs(transform.position.x - El_carmenPlace.position.x) <= 0.5f &&
Mathf.Abs(transform.position.y - El_carmenPlace.position.y) <= 0.5f)
{
transform.position = new Vector2(El_carmenPlace.position.x, El_carmenPlace.position.y);
locked = true;
}
else
{
transform.position = new Vector2(initialPosition.x, initialPosition.y);
}
break;
}
}
}
}
i have try the enable disable ragdoll , scripts that unity post , i created an empty object and tried to add the piece of the puzzle , but i cant? is using rigidbody 2d dunno if it coutns as a rigid body...
Basically i fixed the two major problems , now for the wiinning part im using if (ALtzayanca.locked && Huamantla.locked && El_carmen.locked) , i want to use a tag or something so when everthing is locked , you win
[SerializeField]
private Transform HuamantlPlace;
private float deltaX, deltaY;
public static bool locked;
//use this for initialiozation
void Start()
{
}
private void Update()
{
if (Input.touchCount > 0 && !locked)
{
Touch touch = Input.GetTouch(0);
Vector2 touchPos = Camera.main.ScreenToWorldPoint(touch.position);
switch (touch.phase)
{
case TouchPhase.Began:
if (GetComponent<Collider2D>() == Physics2D.OverlapPoint(touchPos))
{
gameObject.GetComponent<Rigidbody2D>().isKinematic = true;
deltaX = touchPos.x - transform.position.x;
deltaY = touchPos.y - transform.position.y;
}
break;
case TouchPhase.Moved:
if (GetComponent<Collider2D>() == Physics2D.OverlapPoint(touchPos))
transform.position = new Vector2(touchPos.x - deltaX, touchPos.y - deltaY);
break;
case TouchPhase.Ended:
if (Mathf.Abs(transform.position.x - HuamantlPlace.position.x) <= 0.5f &&
Mathf.Abs(transform.position.y - HuamantlPlace.position.y) <= 0.5f)
{
this.gameObject.GetComponent<Rigidbody2D>().isKinematic = true;
transform.position = new Vector2(HuamantlPlace.position.x, HuamantlPlace.position.y);
this.gameObject.GetComponent<Rigidbody2D>().constraints = RigidbodyConstraints2D.FreezePositionX | RigidbodyConstraints2D.FreezePositionY;
locked = true;
}
else
{
this.gameObject.GetComponent<Rigidbody2D>().isKinematic = false;
}
break;
}
}
}
}

Weird Issue Quaternion Rotation in XNA Space Simulator

I have spent 8 hours trying to find a solution.
So here is my problem. My ship is rotating like it's rotating around something, like a string. When I go farther and farther from the starting position, I start rotating more weirder and weirder. Like I am attached to a string.
Here is the code for Rotation and Movement.
public void MoveShip(List<InputAction> InputActionList, GameTime gameTime)
{
float second = (float)gameTime.ElapsedGameTime.TotalSeconds;
float currentTurningSpeed = second * TurningSpeed;
float leftRightRotation = 0;
float upDownRotation = 0;
float linearLeftRightRotation = 0;
foreach(InputAction action in InputActionList)
{
switch(action)
{
case InputAction.Left:
leftRightRotation -= currentTurningSpeed;
break;
case InputAction.Right:
leftRightRotation += currentTurningSpeed;
break;
case InputAction.Up:
upDownRotation += currentTurningSpeed;
break;
case InputAction.Down:
upDownRotation -= currentTurningSpeed;
break;
case InputAction.IncreaseSpeed:
if (ShipSpeed < MaxShipSpeed)
ShipSpeed += Acceleration;
break;
case InputAction.DecreaseSpeed:
if (ShipSpeed > MinShipSpeed)
ShipSpeed -= Acceleration;
break;
case InputAction.LinearLeft:
linearLeftRightRotation += currentTurningSpeed;
break;
case InputAction.LinearRight:
linearLeftRightRotation -= currentTurningSpeed;
break;
case InputAction.Fire1:
WeaponSystem2D.RequestFire(ShipPosition, ShipRotation);
break;
}
}
Quaternion currentRotation = Quaternion.CreateFromAxisAngle(new Vector3(0, 0, 1), leftRightRotation) *
Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), upDownRotation) *
Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), linearLeftRightRotation);
currentRotation.Normalize();
ShipRotation *= currentRotation;
ShipPosition *= Vector3.Transform(new Vector3(0, 0, 1), ShipRotation) * (ShipSpeed * second);
ShipWorld = Matrix.CreateFromQuaternion(ShipRotation) * Matrix.CreateTranslation(ShipPosition);
}
What is the problem? Why is it doing this? I want the ship to rotate on a dime, since it is space.
EDIT:
-The model is not an issue.
EDIT 2: Nevermind, the rotation was actually working, it was my skybox that was broken!
This code is actually perfect, my skybox made it look like it was broken.

Categories

Resources