How to do interchangeable armor on character (low poly models) - animation

I'm currently working on RPG graphically very similar to Runescape (old school), but with my own game system. I am not sure what is the best way to have interchangeable armor system. I am going to create low poly models, as i said, similar to runescape models like here, and want to have possibility to have random variations of armor like here.
There are two ways as I understand, first is just to change mesh of my character model, the second one is to create model of my character and use the bones weights to armor models. I know there is whole topic about the first option here (couldn't make 3rd link) forum.unity3d.com/threads/stitch-multiple-body-parts-into-one-character.16485/, but really? Every qeustion about something similar leads to this topic. But its like 8 years old and for Unity 2.0...Is there simplier way to achieve same results but don't study masterprompt's exhausting explanation which I'm not gonna be able to implement anyway. And for the second way I can't find any hints, except manual and script on unity web for bone weight, which is way too general for my use and my skills. I have spent looking for some solutions (tutorials) for hours, but google keeps popping the same topics, which are 4-8 years old...
Any advice how to choose the best way for changing armors and how to gain any knowledge about these issues? Thank You.

So what I'm doing in my projects is I duplicate my base character .blend file (rig, model) and I remove most of the mesh except for the body part that I want to make the clothing for (chest/legs). I pull it out a bit so the vertices doesn't overlap with base mesh and just save it.
Then in Unity I create a new prefab out of the model I just saved. The hierarchy of a prefab looks like this: parent game object with BoneReplacer.cs script -> child game object with skinned mesh renderer of my clothing.
Then all I have to do is just drag this prefab onto my character prefab so the target variable in this script points to my character's skinned mesh renderer.
This probably isn't the best way to do this but it works for me, maybe it will help you get your head around it and create some better solution.
Heres the BoneReplacer.cs script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BoneReplacer : MonoBehaviour
{
public GameObject target;
SkinnedMeshRenderer myRenderer;
Transform[] newBones;
SkinnedMeshRenderer targetRenderer;
Dictionary<string, Transform> boneMap = new Dictionary<string, Transform>();
void Start()
{
target = transform.parent.parent.gameObject;
targetRenderer = target.GetComponentInChildren<SkinnedMeshRenderer>();
foreach (Transform _bone in targetRenderer.bones)
{
boneMap[_bone.gameObject.name] = _bone;
}
myRenderer = gameObject.GetComponent<SkinnedMeshRenderer>();
newBones = new Transform[myRenderer.bones.Length];
for (int i = 0; i < myRenderer.bones.Length; i++)
{
GameObject _bone = myRenderer.bones[i].gameObject;
if (!boneMap.TryGetValue(_bone.name, out newBones[i]))
{
Debug.Log("Unable to map bone ~" + _bone.name + "~ to target skeleton!");
break;
}
}
myRenderer.bones = newBones;
myRenderer.rootBone = targetRenderer.rootBone;
}
}

Related

How to change the position of cutplane? HelixToolkit.Wpf

I successfully cut an STL model, but I can't change the position of the cut plane.
Structure:
Viewport -> CuttingPlaneGroup -> CuttingPlanes -> Plane3D.
The STL model is in the CuttingPlaneGroup.
Does anyone know how to dynamically change the cut plane position with a slider?
If I change the position of the Plane, nothing happens.
var nj = sender as Slider;
cutPlane.Position.Offset(0, nj.Value, 0);
It seems that once you cut the STL, you can't change it anymore.
Do I have to delete the STL and reload it? That would be harsh.
The STL model is not frozen nor sealed.
EDIT:
In the source code I found if you change the "Operation" or "IsEnabled" property, it forces the model to update. Changing the normal and operation is nearly 2x faster executing than changing the IsEnabled. Still, it takes 400-500 ms to update.
EDIT2:
I took the source code and exposed private void ApplyCuttingGeometries(bool forceUpdate = false) to public void. The result is same as changing the operation (~400ms).
The code now looks like:
var nj = sender as Slider;
cp.Position = new Point3D(0, nj.Value, 0); // cp = Plane3D
ctp.ApplyCuttingGeometries(true); //ctp = CuttingPlaneGroup
Any better solution?
The cut plane in wpf version is basically create a new cut model every time.
You don't need to use cutting group. You can take a look the cut plane group source code and implement the model update yourself.

Passing list as a parameter: player vs the world

I'm creating a top-down 2D game.
Classes in question are Level and Entity.
In Level I have a Map, but let's just think of that class as a list of items like walls and other stuff you can imagine will have a body, which is actually a XNA's Rectangle.
Now, in Level's Update function, I'll be putting Entity's function that will resolve all collisions (walls, pickups, other entities, traps, etc), and I am questioning the best way of letting each Entity know what's around him. By doing that I want to achieve the freedom of creating different Entityes such as different players, enemies, bosses... Goal is a good parent class for everything that should feel alive to the player playing the game.
So, I want to get a good performance for this function (that'll resolve collisions), because I plan on making maps that'll have around 1000 different items and many entities, and can't decide how to go about it.
The structure is something like this: Level has a list of items (walls, pickups, traps...) and a list of entities (players, enemies, bosses, pets, mounts, whatever...), and in each update of level I loop trough entities and do Update for each.
Question Do I:
1) send whole list of items to each entity('s update method) and calculate distances from each item and resolve collision
2) calculate closest items to the entity in level's update method and then send smaller list of items to the entity, which will then resolve collision
3) (this I just thought of) pass list of XNA's Rectangles and type of item (that could mean I must make a new class or new function for map class that will return 2 lists: rectangles and item types)
4) pass the whole map, but in a matix (because map will be a grid, not items nor player's rectangles will rotate) of integers that'll have something like "1 for wall, 0 for nothing, 2 for trap, 3 for health-pack, etc). But this will resolve only the map, because other entities won't all be in grid coordinates (wall's positions will be like 32x32, 0x64, etc, and all will be 32x32, but entities won't. They'll be 32x16, and their position may vary. That also crossed my mind just now.
Note that both entities and items will most likely have much more than Rectangle for body. There will be textures, animations, and other basic types of variables for different purpose, and most of them won't be needed for entities collision resolution with that item. When colliding with a wall, entity won't need that items image to resolve collision, but it will need items (lets say) X value if that item is a healt potion.
How would you resolve this so the code is efficient, or how did you resolve this in your game?
I am looking for simpicity and efficiency, and that's what I will be looking for in your answer.
I haven't tested this code at all, so if it doesn't work, thats why.
Given that Entity is a struct with the following code,
struct Entity{
Rectangle pos;
Texture2D tex;
bool hasAgency;
public Entity(Rectangle pos, Texture2D tex, bool hasAgency){
this.pos = pos;
this.tex = tex;
this.hasAgency = hasAgency;
}
}
then this should work.
List<Entity> entityList = new List<Entity>//your entities are here
for(int testIndex=0; testIndex<entityList.Count; testIndex++){
for(int entityBeingTested = 0; entityBeingTested<entityList.Count; entityBeingTested++){
if(testIndex!=entityBeingTested && entityList[testIndex].hasAgency)
{
if(entityList[testIndex].pos.Intersects(entityList[entityBeingTested.pos]))
//hit logic here
}
}
}

libGDX- Exact collision detection - Polygon creation?

I've got a question about libGDX collision detection. Because it's a rather specific question I have not found any good solution on the internet yet.
So, I already created "humans" that consist of different body parts, each with rectangle-shaped collision detection.
Now I want to implement weapons and skills, which for example look like this:
Skill example image
Problem
Working with rectangles in collision detections would be really frustrating for players when there are skills like this: They would dodge a skill successfully but the collision detector would still damage them.
Approach 1:
Before I started working with Libgdx I have created an Android game with a custom engine and similar skills. There I solved the problem following way:
Detect rectangle collision
Calculate overlapping rectangle section
Check every single pixel of the overlapping part of the skill for transparency
If there is any non-transparent pixel found -> Collision
That's a kind of heavy way, but as only overlapping pixels are checked and the rest of the game is really light, it works completely fine.
At the moment my skill images are loaded as "TextureRegion", where it is not possible to access single pixels.
I have found out that libGDX has a Pixmap class, which would allow such pixel checks. Problem is: having them loaded as Pixmaps additionally would 1. be even more heavy and 2. defeat the whole purpose of the Texture system.
An alternative could be to load all skills as Pixmap only. What do you think: Would this be a good way? Is it possible to draw many Pixmaps on the screen without any issues and lag?
Approach 2:
An other way would be to create Polygons with the shape of the skills and use them for the collision detection.
a)
But how would I define a Polygon shape for every single skill (there are over 150 of them)? Well after browsing a while, I found this useful tool: http://www.aurelienribon.com/blog/projects/physics-body-editor/
it allows to create Polygon shapes by hand and then save them as JSON files, readable by the libGDX application. Now here come the difficulties:
The Physics Body Editor is connected to Box2d (which I am not using). I would either have to add the whole Box2d physics engine (which I do not need at all) just because of one tiny collision detection OR I would have to write a custom BodyEditorLoader which would be a tough, complicated and time-intensive task
Some images of the same skill sprite have a big difference in their shapes (like the second skill sprite example). When working with the BodyEditor tool, I would have to not only define the shape of every single skill, but I would have to define the shape of several images (up to 12) of every single skill. That would be extremely time-intensive and a huge mess when implementing these dozens of polygon shapes
b)
If there is any smooth way to automatically generate Polygons out of images, that could be the solution. I could simply connect every sprite section to a generated polygon and check for collisions that way. There are a few problems though:
Is there any smooth tool which can generate Polygon shapes out of an image (and does not need too much time therefor)?
I don't think that a tool like this (if one exists) can directly work with Textures. It would probably need Pixmaps. It would not be needed to keep te Pixmaps loaded after the Polygon creation though. Still an extremely heavy task!
My current thoughts
I'm stuck at this point because there are several possible approaches but all of them have their difficulties. Before I choose one path and continue coding, it would be great if you could leave some of your ideas and knowledge.
There might be helpful classes and code included in libGDX that solve my problems within seconds - as I am really new at libGDX I just don't know a lot about it yet.
Currently I think I would go with approach 1: Work with pixel detection. That way I made exact collision detections possible in my previous Android game.
What do you think?
Greetings
Felix
I, personally, would feel like pixel-to-pixel collision would be overkill on performance and provide some instances where I would still feel cheated - (I got hit by the handle of the axe?)
If it were me, I would add a "Hitbox" to each skill. StreetFighter is a popular game which uses this technique. (newer versions are in 3D, but hitbox collision is still 2D) Hitboxes can change frame-by-frame along with the animation.
Empty spot here to add example images - google "Streetfighter hitbox" in the meantime
For your axe, there could be a defined rectangle hitbox along the edge of one or both ends - or even over the entire metal head of the axe.
This keeps it fairly simple, without having to mess with exact polygons, but also isn't overly performance heavy like having every single pixel being its own hitbox.
I've used that exact body editor you referenced and it has the ability to generate polygons and/or circles for you. I also made a loader for the generated JSON with the Jackson library. This may not be the answer for you since you'd have to implement box2d. But here's how how I did it anyway.
/**
* Adds all the fixtures defined in jsonPath with the name'lookupName', and
* attach them to the 'body' with the properties defined in 'fixtureDef'.
* Then converts to the proper scale with 'width'.
*
* #param body the body to attach fixtures to
* #param fixtureDef the fixture's properties
* #param jsonPath the path to the collision shapes definition file
* #param lookupName the name to find in jsonPath json file
* #param width the width of the sprite, used to scale fixtures and find origin.
* #param height the height of the sprite, used to find origin.
*/
public void addFixtures(Body body, FixtureDef fixtureDef, String jsonPath, String lookupName, float width, float height) {
JsonNode collisionShapes = null;
try {
collisionShapes = json.readTree(Gdx.files.internal(jsonPath).readString());
} catch (JsonProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
for (JsonNode node : collisionShapes.findPath("rigidBodies")) {
if (node.path("name").asText().equals(lookupName)) {
Array<PolygonShape> polyShapes = new Array<PolygonShape>();
Array<CircleShape> circleShapes = new Array<CircleShape>();
for (JsonNode polygon : node.findPath("polygons")) {
Array<Vector2> vertices = new Array<Vector2>(Vector2.class);
for (JsonNode vector : polygon) {
vertices.add(new Vector2(
(float)vector.path("x").asDouble() * width,
(float)vector.path("y").asDouble() * width)
.sub(width/2, height/2));
}
polyShapes.add(new PolygonShape());
polyShapes.peek().set(vertices.toArray());
}
for (final JsonNode circle : node.findPath("circles")) {
circleShapes.add(new CircleShape());
circleShapes.peek().setPosition(new Vector2(
(float)circle.path("cx").asDouble() * width,
(float)circle.path("cy").asDouble() * width)
.sub(width/2, height/2));
circleShapes.peek().setRadius((float)circle.path("r").asDouble() * width);
}
for (PolygonShape shape : polyShapes) {
Vector2 vectors[] = new Vector2[shape.getVertexCount()];
for (int i = 0; i < shape.getVertexCount(); i++) {
vectors[i] = new Vector2();
shape.getVertex(i, vectors[i]);
}
shape.set(vectors);
fixtureDef.shape = shape;
body.createFixture(fixtureDef);
}
for (CircleShape shape : circleShapes) {
fixtureDef.shape = shape;
body.createFixture(fixtureDef);
}
}
}
}
And I would call it like this:
physics.addFixtures(body, fixtureDef, "ship/collision_shapes.json", shipType, width, height);
Then for collision detection:
public ContactListener shipsExplode() {
ContactListener listener = new ContactListener() {
#Override
public void beginContact(Contact contact) {
Body bodyA = contact.getFixtureA().getBody();
Body bodyB = contact.getFixtureB().getBody();
for (Ship ship : ships) {
if (ship.body == bodyA) {
ship.setExplode();
}
if (ship.body == bodyB) {
ship.setExplode();
}
}
}
};
return listener;
}
then you would add the listener to the world:
world.setContactListener(physics.shipsExplode());
my sprites' width and height were small since you're dealing in meters not pixels once you start using box2d. One sprite height was 0.8f and width was 1.2f for example. If you made the sprites width and height in pixels the physics engine hits speed limits that are built in http://www.iforce2d.net/b2dtut/gotchas
Don't know if this still matter to you guys, but I built a small python script that returns the pixels positions of the points in the edges of the image. There is room to improve the script, but for me, for now its ok...
from PIL import Image, ImageFilter
filename = "dship1"
image = Image.open(filename + ".png")
image = image.filter(ImageFilter.FIND_EDGES)
image.save(filename + "_edge.png")
cols = image.width
rows = image.height
points = []
w = 1
h = 1
i = 0
for pixel in list(image.getdata()):
if pixel[3] > 0:
points.append((w, h))
if i == cols:
w = 0
i = 0
h += 1
w += 1
i += 1
with open(filename + "_points.txt", "wb") as nf:
nf.write(',\n'.join('%s, %s' % x for x in points))
In case of updates you can find them here: export positions

How to give control back to animation in Unity3D once altering objects location

I have a character made of up child objects that are animated using Unity3D's animation system.
While the player is walking, I can programmatically move the hand object up to catch a ball using the following code.
hand.position.y = ball.transform.position.y;
I need the hand object to go back to following the walk animation after it touches the ball, but instead it just stays at the exact position since it was set.
You want to use inverse kinematics and let Unity do the work of figuring out positioning for you. Here's a quick-and-dirty (untested) example for catching a ball (it's in C#, but it should be pretty similar for UnityScript):
// in a script on the same GameObject as your animation controller
bool isCatching;
Transform ball;
void OnAnimatorIK (int layer) {
if (isCatching) {
// set position and rotation weights for your catching hand
animator.SetIKPosition(AvatarIKGoal.RightHand, ball.position);
animator.SetIKRotation(AvatarIKGoal.RightHand, ball.rotation);
} else {
// return your position and rotation weights back to their defaults (probably 0f?)
}
}
You'll need to do some work (possibly raycasting or just checking distance and direction) to determine when to set the isCatching flag to true, and you'll want to play with the weights for position and rotation to make it look natural. The IK manual entry has more detailed information.

XNA: Identifying identical sprites created with for loop

G'day all,
In short, I'm using a for loop to create a bunch of identical sprites that I want to bounce around the screen. The problem is how do I write a collision detection process for the sprites. I have used the process of placing rectangles around sprites and using the .intersects method for rectangles but in that case I created each sprite separately and could identify each one uniquely. Now I have a bunch of sprites but no apparent way to pick one from another.
In detail, if I create an object called Bouncer.cs and give it the movement instructions in it's update() method then create a bunch of sprites using this in Game.cs:
for (int i = 1; i < 5; ++i)
{
Vector2 position = new Vector2(i * 50, i * 50);
Vector2 direction = new Vector2(i * 10, i * 10);
Vector2 velocity = new Vector2(10);
Components.Add(new Bouncer(this, position, direction, velocity, i));
}
base.Initialize();
I can draw a rectangle around each one using:
foreach (Bouncer component1 in Components)
{
Bouncer thing = (Bouncer)component1;
Rectangle thingRectangle;
thingRectangle = new Rectangle((int)thing.position.X, (int)thing.position.Y, thing.sprite.Width, thing.sprite.Height);
But now, how do I check for a collision? I can hardly use:
if (thingRectangle.Intersects(thingRectangle))
I should point out I'm a teacher by trade and play with coding to keep my brain from turning to mush. Recently I have been working with Python and with Python I could just put all the sprites into a list:
sprites[];
Then I could simply refer to each as sprite[1] or sprite[2] or whatever its index in the list is. Does XNA have something like this?
Please let me know if any more code needs to be posted.
Thanks,
Andrew.
One solution, which I use in my game engine, is to have a Logic code run inside the objects for every game Update, ie. every frame. It seems you already do this, according to the variable names, which indicate you run some physics code in the objects to update their positions.
You might also want to create the collision rectangle inside the Bouncer's constructor so it's more accessible and you make good use of object oriented programming, maybe even make it an accessor, so you can make it update every time you call it instead of manually updating the bounding/collision box. For example:
public Rectangle #BoundingBox {
get { return new Rectangle(_Position.X, _Position.Y, width, height); }
}
Whichever way works, but the collision checks can be run inside the Bouncer object. You can either make the reference list of the Bouncer objects static or pass it to the objects itself. The code for collisions is very simply:
foreach(Bouncer bouncer in Components) //Components can be a static List or you can pass it on in the constructor of the Bouncer object
{
if (bouncer.BoundingBox.Intersects(this.BoundingBox))
{
//they collided
}
}

Resources