A structure is a hierarchical collection of data of possibly different datatypes, while a union is set of different datatypes for accessing the same data.
In SystemVerilog, an unpacked structure gives you the convenience of working with a collection of data as an aggregate. You can declare, copy, assign, compare, connect, etc. that collection in a single operation rather than having to refer to each individual pieces of data separately. There is rarely any need for an unpacked union. Its main purpose is compatibility in the DPI interface to C. SystemVerilog does not define the memory layout of an unpacked structure or union in its implementation.
A packed structure in SystemVerilog gives you an alternative way to access fields of a signal by name instead of by bit position. For example
typedef struct packed {
logic [2:0] field1; // 3-bits
logic [4:0] field2; // 5-bits
} signal_t; // 8-bits
You can now declare either a wire or variable with that type
wire signal_t sigA;
var signal_t sigB;
(the var keyword is implicit is most places except in a port declaration)
You can now access field1 as either sigA[7:5] or sigA.field1. You can think of a packed structure as an implicit packed union with a single bit vector whose length is the sum of all the packed structure members.
A packed union is set of datatypes all with the exact same length that give you different ways of accessing the same data.
typedef union packed {
int A;
bit [7:0] B[4];
bit [15:0] C[2];
} ABC_u;
ABC_u abc;
Now abc.B[3:2], abc.C[1], and abc[31:16] all refer to the same set of bits.